]> git.proxmox.com Git - pve-edk2-firmware.git/commitdiff
bump version to 4.2023.08-4 master
authorFabian Grünbichler <f.gruenbichler@proxmox.com>
Thu, 15 Feb 2024 07:57:01 +0000 (08:57 +0100)
committerFabian Grünbichler <f.gruenbichler@proxmox.com>
Thu, 15 Feb 2024 08:55:40 +0000 (09:55 +0100)
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
35 files changed:
Makefile
debian/README.Proxmox-VE
debian/binary-check.allow
debian/binary-check.remove
debian/changelog
debian/control
debian/copyright
debian/edk2-vars-generator.py
debian/find-binaries.py
debian/legacy-2M-builds/OVMF_CODE.fd [new file with mode: 0644]
debian/legacy-2M-builds/OVMF_CODE.secboot.fd [new file with mode: 0644]
debian/legacy-2M-builds/OVMF_VARS.fd [new file with mode: 0644]
debian/legacy-2M-builds/OVMF_VARS.ms.fd [new file with mode: 0644]
debian/patches/ArmVirtPkg-disable-the-EFI_MEMORY_ATTRIBUTE-protocol.patch [new file with mode: 0644]
debian/patches/CVE-2023-45229_45237.patch [new file with mode: 0644]
debian/patches/CVE-2023-48733-Disable-the-Shell-when-SecureBoot-is-enabled.patch [new file with mode: 0644]
debian/patches/Revert-ArmVirtPkg-make-EFI_LOADER_DATA-non-executabl.patch [new file with mode: 0644]
debian/patches/no-stack-protector-all-archs.diff
debian/patches/series
debian/patches/x64-baseline-abi.patch [new file with mode: 0644]
debian/pve-edk2-firmware-aarch64.install [new file with mode: 0644]
debian/pve-edk2-firmware-legacy.install [new file with mode: 0644]
debian/pve-edk2-firmware-legacy.links [new file with mode: 0644]
debian/pve-edk2-firmware-ovmf.install [new file with mode: 0644]
debian/pve-edk2-firmware-riscv.install [new file with mode: 0644]
debian/pve-edk2-firmware.install [deleted file]
debian/python/UEFI/Filesystems.py
debian/python/UEFI/Qemu.py
debian/python/UEFI/SignedBinary.py [new file with mode: 0644]
debian/rules
debian/source/include-binaries [new file with mode: 0644]
debian/source/lintian-overrides [new file with mode: 0644]
debian/tests/control
debian/tests/shell.py
edk2

index ebeeb6bed4c0c92dd50ac7c559b7ca166d216bdc..6091ce7b4ca2a1e2e42bba41666ad87b8725afb2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,54 +3,73 @@ include /usr/share/dpkg/pkg-info.mk
 PACKAGE=pve-edk2-firmware
 
 SRCDIR=edk2
-BUILDDIR ?= ${PACKAGE}-${DEB_VERSION_UPSTREAM}
+BUILDDIR ?= $(PACKAGE)-$(DEB_VERSION_UPSTREAM)
+ORIG_SRC_TAR=$(PACKAGE)_$(DEB_VERSION_UPSTREAM).orig.tar.gz
 
-GITVERSION:=$(shell git rev-parse HEAD)
+DSC=$(PACKAGE)_$(DEB_VERSION).dsc
 
-DEB=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}_all.deb
-DSC=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}.dsc
+# transitional virtual package depending on the amd64 ones
+VIRTUAL_DEB = $(PACKAGE)_$(DEB_VERSION)_all.deb
+AMD64_DEB = $(PACKAGE)-legacy_$(DEB_VERSION)_all.deb $(PACKAGE)-ovmf_$(DEB_VERSION)_all.deb
+AARCH64_DEB = $(PACKAGE)-aarch64_$(DEB_VERSION)_all.deb
+RISCV_DEB = $(PACKAGE)-riscv_$(DEB_VERSION)_all.deb
 
-all: ${DEB}
-       @echo ${DEB}
+DEBS = $(VIRTUAL_DEB) $(AMD64_DEB) $(AARCH64_DEB) $(RISCV_DEB)
 
-${BUILDDIR}: ${SRCDIR}/Readme.md
-       rm -rf ${BUILDDIR}
-       cp -rpa ${SRCDIR} ${BUILDDIR}
-       cp -a debian ${BUILDDIR}
-       echo "git clone git://git.proxmox.com/git/pve-edk2-firmware.git\\ngit checkout ${GITVERSION}" > ${BUILDDIR}/debian/SOURCE
+all: $(DEBS)
+       @echo $(DEBS)
+
+$(BUILDDIR): $(SRCDIR)/Readme.md
+       rm -rf $@ $@.tmp
+       cp -rpa $(SRCDIR) $@.tmp
+       rm -rf $@.tmp/ArmPkg/Library/GccLto/*.a
+       cp -a debian $@.tmp
+       echo "git clone git://git.proxmox.com/git/pve-edk2-firmware.git\\ngit checkout $(shell git rev-parse HEAD)" > $@.tmp/debian/SOURCE
+       mv $@.tmp $@
 
 .PHONY: deb
-deb: ${DEB}
-${DEB}: ${BUILDDIR}
-       cd ${BUILDDIR}; dpkg-buildpackage -b -uc -us
-       lintian ${DEB}
-       @echo ${DEB}
+deb: $(DEBS)
+$(AMD64_DEB) $(AARCH64_DEB) $(RISCV_DEB): $(VIRTUAL_DEB)
+$(VIRTUAL_DEB): $(BUILDDIR)
+       cd $(BUILDDIR); dpkg-buildpackage -b -uc -us
+       lintian $(DEBS)
+       @echo $(DEBS)
+
+$(ORIG_SRC_TAR): $(BUILDDIR)
+       tar czf $(ORIG_SRC_TAR) --exclude="$(BUILDDIR)/debian" $(BUILDDIR)
+
+$(DSC): $(BUILDDIR) $(ORIG_SRC_TAR)
+       cd $(BUILDDIR); dpkg-buildpackage -S -uc -us -d
+
+sbuild: $(DSC)
+       sbuild $(DSC)
 
 .PHONY: dsc
-dsc: ${DSC}
-${DSC}: ${BUILDDIR}
-       cd ${BUILDDIR}; dpkg-buildpackage -S -uc -us -d
-       lintian ${DSC}
+dsc: $(DSC)
+       $(MAKE) clean
+       $(MAKE) $(DSC)
+       lintian $(DSC)
 
 .PHONY: submodule
 submodule:
        test -e edk2/Maintainers.txt || git submodule update --init --recursive
 
-${SRCDIR}/Readme.md: submodule
+$(SRCDIR)/Readme.md: submodule
 
 .PHONY: update_modules
 update_modules: submodule
        git submodule foreach 'git pull --ff-only origin master'
 
 .PHONY: upload
-upload: ${DEB}
-       tar cf - ${DEB}|ssh -X repoman@repo.proxmox.com -- upload --product pve --dist buster
+upload: UPLOAD_DIST ?= $(DEB_DISTRIBUTION)
+upload: $(DEBS)
+       tar cf - $(DEBS)|ssh -X repoman@repo.proxmox.com -- upload --product pve --dist $(UPLOAD_DIST)
 
 .PHONY: distclean clean
 distclean: clean
 clean:
-       rm -rf *~ debian/*~ *.deb ${PACKAGE}-*/ *.tar.gz *.changes *.dsc *.buildinfo
+       rm -rf *.deb $(PACKAGE)-[0-9]*/ $(PACKAGE)*.tar* *.changes *.dsc *.buildinfo *.build
 
 .PHONY: dinstall
-dinstall: ${DEB}
-       dpkg -i ${DEB}
+dinstall: $(VIRTUAL_DEB) $(AMD64_DEB)
+       dpkg -i $^
index ab231745e742405c11983180390593740f296240..282d7a714e0ff092543a55b9e429b7f6331f3e38 100644 (file)
@@ -40,6 +40,8 @@ OVMF_VARS.ms.fd
   These images are the same as their "4M" variants, but for use with guests
   using a 2MB flash device. 2MB flash is no longer considered sufficient for
   use with Secure Boot. This is provided only for backwards compatibility.
+  NOTE: As 2MB support was removed with 2023.08 release, we now ship them as
+  static builds from our last release before that (2023.02)
 
 OVMF_CODE_4M.snakeoil.fd
 OVMF_VARS_4M.snakeoil.fd
@@ -99,4 +101,4 @@ PkKek-1-snakeoil.pem
   OVMF_VARS.snakeoil.fd template. The password for the key is
   'snakeoil'.
 
- -- dann frazier <dannf@debian.org>, Fri,  4 Feb 2022 17:01:31 -0700
+ -- Proxmox Support Team <support@proxmox.com>, dann frazier <dannf@debian.org>, Fri,  4 Feb 2022 17:01:31 -0700
index 749a2f86ec6a20a79aeaeb44bb7899b9b6a8321b..18c296181360eb725a67096ada34f3590a20b6d0 100644 (file)
@@ -1,67 +1,50 @@
-.gitmodules
-AppPkg/Applications/Python/Python-2.7.2/Demo/comparisons/patterns
-AppPkg/Applications/Python/Python-2.7.2/Demo/md5test/foo
-AppPkg/Applications/Python/Python-2.7.2/Demo/parser/FILES
-AppPkg/Applications/Python/Python-2.7.2/Demo/pdist/rcsbump
-AppPkg/Applications/Python/Python-2.7.2/Demo/pdist/rcvs
-AppPkg/Applications/Python/Python-2.7.2/Demo/pdist/rrcs
-AppPkg/Applications/Python/Python-2.7.2/Demo/scripts/newslist.doc
-AppPkg/Applications/Python/Python-2.7.2/Grammar/Grammar
-AppPkg/Applications/Python/Python-2.7.2/Lib/distutils/command/command_template
-AppPkg/Applications/Python/Python-2.7.2/Lib/distutils/tests/Setup.sample
-AppPkg/Applications/Python/Python-2.7.2/Lib/email/test/data/audiotest.au
-AppPkg/Applications/Python/Python-2.7.2/Lib/pdb.doc
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/185test.db
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/Sine-1000Hz-300ms.aif
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/audiotest.au
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/check_soundcard.vbs
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/empty.vbs
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/greyrgb.uue
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/randv2_32.pck
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/randv2_64.pck
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/randv3.pck
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/testimg.uue
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/testimgr.uue
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/testrgb.uue
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/testtar.tar
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/xmltestdata/test.xml.out
-AppPkg/Applications/Python/Python-2.7.2/Lib/test/zipdir.zip
-AppPkg/Applications/Python/Python-2.7.2/Lib/wsgiref.egg-info
-AppPkg/Applications/Python/Python-2.7.2/Modules/zlib/make_vms.com
-AppPkg/Applications/Python/Python-2.7.2/Parser/Python.asdl
-AppPkg/Applications/Python/Python-2.7.2/Tools/compiler/ACKS
-AppPkg/Applications/Python/Python-2.7.2/Tools/msi/msisupport.mak
-AppPkg/Applications/Python/Python-2.7.2/Tools/scripts/2to3
-AppPkg/Applications/Python/Python-2.7.2/Tools/scripts/dutree.doc
-AppPkg/Applications/Python/Python-2.7.2/Tools/scripts/idle
-AppPkg/Applications/Python/Python-2.7.2/Tools/scripts/pydoc
-AppPkg/Applications/Python/Python-2.7.2/Tools/scripts/pydocgui.pyw
-AppPkg/Applications/Python/Python-2.7.2/Tools/unicode/python-mappings/CP1140.TXT
-AppPkg/Applications/Python/Python-2.7.2/Tools/unicode/python-mappings/KOI8-U.TXT
-AppPkg/Applications/Python/Python-2.7.2/Tools/unicode/python-mappings/TIS-620.TXT
-AppPkg/Applications/Python/Python-2.7.2/Tools/world/world
-ArmPkg/Library/ArmSoftFloatLib/bits32/softfloat-macros
-ArmPkg/Library/ArmSoftFloatLib/softfloat-specialize
+ArmPkg/Library/GnuNoteBti.bin
+BaseTools/BinPipWrappers/PosixLike/AmlToC
+BaseTools/BinPipWrappers/PosixLike/BPDG
+BaseTools/BinPipWrappers/PosixLike/BrotliCompress
+BaseTools/BinPipWrappers/PosixLike/build
+BaseTools/BinPipWrappers/PosixLike/DevicePath
+BaseTools/BinPipWrappers/PosixLike/Ecc
+BaseTools/BinPipWrappers/PosixLike/EfiRom
+BaseTools/BinPipWrappers/PosixLike/GenCrc32
+BaseTools/BinPipWrappers/PosixLike/GenDepex
+BaseTools/BinPipWrappers/PosixLike/GenerateCapsule
+BaseTools/BinPipWrappers/PosixLike/GenFds
+BaseTools/BinPipWrappers/PosixLike/GenFfs
+BaseTools/BinPipWrappers/PosixLike/GenFv
+BaseTools/BinPipWrappers/PosixLike/GenFw
+BaseTools/BinPipWrappers/PosixLike/GenPatchPcdTable
+BaseTools/BinPipWrappers/PosixLike/GenSec
+BaseTools/BinPipWrappers/PosixLike/LzmaCompress
+BaseTools/BinPipWrappers/PosixLike/LzmaF86Compress
+BaseTools/BinPipWrappers/PosixLike/PatchPcdValue
+BaseTools/BinPipWrappers/PosixLike/Pkcs7Sign
+BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256GenerateKeys
+BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256Sign
+BaseTools/BinPipWrappers/PosixLike/Split
+BaseTools/BinPipWrappers/PosixLike/TargetTool
+BaseTools/BinPipWrappers/PosixLike/TianoCompress
+BaseTools/BinPipWrappers/PosixLike/Trim
+BaseTools/BinPipWrappers/PosixLike/UPT
+BaseTools/BinPipWrappers/PosixLike/VfrCompile
+BaseTools/BinPipWrappers/PosixLike/VolInfo
+BaseTools/BinWrappers/PosixLike/AmlToC
 BaseTools/BinWrappers/PosixLike/BPDG
-BaseTools/BinWrappers/PosixLike/BootSectImage
-BaseTools/BinWrappers/PosixLike/Brotli
 BaseTools/BinWrappers/PosixLike/BrotliCompress
+BaseTools/BinWrappers/PosixLike/build
 BaseTools/BinWrappers/PosixLike/DevicePath
 BaseTools/BinWrappers/PosixLike/Ecc
-BaseTools/BinWrappers/PosixLike/EfiLdrImage
 BaseTools/BinWrappers/PosixLike/EfiRom
-BaseTools/BinWrappers/PosixLike/GenerateCapsule
+BaseTools/BinWrappers/PosixLike/FMMT
 BaseTools/BinWrappers/PosixLike/GenCrc32
 BaseTools/BinWrappers/PosixLike/GenDepex
+BaseTools/BinWrappers/PosixLike/GenerateCapsule
 BaseTools/BinWrappers/PosixLike/GenFds
 BaseTools/BinWrappers/PosixLike/GenFfs
 BaseTools/BinWrappers/PosixLike/GenFv
 BaseTools/BinWrappers/PosixLike/GenFw
-BaseTools/BinWrappers/PosixLike/GenPage
 BaseTools/BinWrappers/PosixLike/GenPatchPcdTable
 BaseTools/BinWrappers/PosixLike/GenSec
-BaseTools/BinWrappers/PosixLike/GenVtf
-BaseTools/BinWrappers/PosixLike/GnuGenBootSector
 BaseTools/BinWrappers/PosixLike/LzmaCompress
 BaseTools/BinWrappers/PosixLike/LzmaF86Compress
 BaseTools/BinWrappers/PosixLike/PatchPcdValue
@@ -75,9 +58,11 @@ BaseTools/BinWrappers/PosixLike/Trim
 BaseTools/BinWrappers/PosixLike/UPT
 BaseTools/BinWrappers/PosixLike/VfrCompile
 BaseTools/BinWrappers/PosixLike/VolInfo
-BaseTools/BinWrappers/PosixLike/build
 BaseTools/BuildEnv
+BaseTools/Conf/diff.order
+BaseTools/Conf/gitattributes
 BaseTools/Conf/XMLSchema/DistributionPackage.xsd
+BaseTools/ReadMe.rst
 BaseTools/Scripts/PackageDocumentTools/packagedocapp.pyw
 BaseTools/Source/C/Makefiles/ms.app
 BaseTools/Source/C/Makefiles/ms.common
@@ -90,23 +75,267 @@ BaseTools/Source/C/VfrCompile/Pccts/RIGHTS
 BaseTools/Source/Python/Ecc/CParser4/C.g4
 BaseTools/Source/Python/Pkcs7Sign/TestRoot.cer
 BaseTools/Source/Python/Rsa2048Sha256Sign/TestSigningPublicKey.bin
-BeagleBoardPkg/ConfigurationHeader.dat
+**/*.cmake
+**/*.conf
+CryptoPkg/Library/OpensslLib/openssl/apps/demoSRP/srp_verifier.txt.attr
+CryptoPkg/Library/OpensslLib/openssl/apps/insta.ca.crt
+CryptoPkg/Library/OpensslLib/openssl/apps/*.srl
+CryptoPkg/Library/OpensslLib/openssl/config
+CryptoPkg/Library/OpensslLib/openssl/config.com
+CryptoPkg/Library/OpensslLib/openssl/Configurations/common0.tmpl
+CryptoPkg/Library/OpensslLib/openssl/Configurations/descrip.mms.tmpl
+CryptoPkg/Library/OpensslLib/openssl/Configurations/gentemplate.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/INTERNALS.Configure
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/AIX.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/BASE.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/Cygwin.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/mingw.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/Unix.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/VMS.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/Windows/cppbuilder.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/Windows/MSVC.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/platform/Windows.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/unix-checker.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/unix-Makefile.tmpl
+CryptoPkg/Library/OpensslLib/openssl/Configurations/windows-checker.pm
+CryptoPkg/Library/OpensslLib/openssl/Configurations/windows-makefile.tmpl
+CryptoPkg/Library/OpensslLib/openssl/Configure
+CryptoPkg/Library/OpensslLib/openssl/crypto/des/asm/des_enc.m4
+CryptoPkg/Library/OpensslLib/openssl/crypto/err/openssl.ec
+CryptoPkg/Library/OpensslLib/openssl/crypto/objects/obj_mac.num
+CryptoPkg/Library/OpensslLib/openssl/crypto/perlasm/s390x.pm
+CryptoPkg/Library/OpensslLib/openssl/demos/bio/descrip.mms
+CryptoPkg/Library/OpensslLib/openssl/demos/bio/shared.opt
+CryptoPkg/Library/OpensslLib/openssl/demos/bio/static.opt
+CryptoPkg/Library/OpensslLib/openssl/doc/images/openssl.svg
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/cipher.dot
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/digest.dot
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/kdf.dot
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/lifecycles.ods
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/mac.dot
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/pkey.dot
+CryptoPkg/Library/OpensslLib/openssl/doc/life-cycles/rand.dot
+CryptoPkg/Library/OpensslLib/openssl/doc/perlvars.pm
+CryptoPkg/Library/OpensslLib/openssl/engines/e_afalg.ec
+CryptoPkg/Library/OpensslLib/openssl/engines/e_capi.ec
+CryptoPkg/Library/OpensslLib/openssl/engines/e_dasync.ec
+CryptoPkg/Library/OpensslLib/openssl/engines/e_loader_attic.ec
+CryptoPkg/Library/OpensslLib/openssl/engines/e_ossltest.ec
+CryptoPkg/Library/OpensslLib/openssl/external/perl/Text-Template-1.56/Changes
+CryptoPkg/Library/OpensslLib/openssl/external/perl/Text-Template-1.56/INSTALL
+CryptoPkg/Library/OpensslLib/openssl/external/perl/Text-Template-1.56/lib/Text/Template.pm
+CryptoPkg/Library/OpensslLib/openssl/external/perl/Text-Template-1.56/lib/Text/Template/Preprocess.pm
+CryptoPkg/Library/OpensslLib/openssl/external/perl/Text-Template-1.56/MANIFEST
+CryptoPkg/Library/OpensslLib/openssl/external/perl/Text-Template-1.56/SIGNATURE
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/DIGESTS.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/DSA.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/EC.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/ECX.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/NIST.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/oids_to_c.pm
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/RSA.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/SM2.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/common/der/wrap.asn1
+CryptoPkg/Library/OpensslLib/openssl/providers/fips.checksum
+CryptoPkg/Library/OpensslLib/openssl/providers/fips.module.sources
+CryptoPkg/Library/OpensslLib/openssl/providers/fips-sources.checksums
+CryptoPkg/Library/OpensslLib/openssl/test/certs/bad.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/cyrillic_crl.utf8
+CryptoPkg/Library/OpensslLib/openssl/test/certs/cyrillic.msb
+CryptoPkg/Library/OpensslLib/openssl/test/certs/cyrillic.utf8
+CryptoPkg/Library/OpensslLib/openssl/test/certs/embeddedSCTs1.tlssct
+CryptoPkg/Library/OpensslLib/openssl/test/certs/ext-check.csr
+CryptoPkg/Library/OpensslLib/openssl/test/certs/interCA.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/leaf-encrypted.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/leaf.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/rootCA.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/sm2.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/sm2-root.crt
+CryptoPkg/Library/OpensslLib/openssl/test/certs/sm2-root.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/subinterCA.key
+CryptoPkg/Library/OpensslLib/openssl/test/certs/v3-certs-RC2.p12
+CryptoPkg/Library/OpensslLib/openssl/test/certs/v3-certs-TDES.p12
+CryptoPkg/Library/OpensslLib/openssl/test/certs/x509-check.csr
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/bad_bio.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/bad_cert.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/bad-cms.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/bad_generalname.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/bad-int-pad0.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/bad-int-padminus1.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/high_tag.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/int0.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/int1.der
+CryptoPkg/Library/OpensslLib/openssl/test/d2i-tests/intminus1.der
+CryptoPkg/Library/OpensslLib/openssl/test/data2.bin
+CryptoPkg/Library/OpensslLib/openssl/test/data.bin
+CryptoPkg/Library/OpensslLib/openssl/test/ocsp-tests/*.ors
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/04-test_pem_reading_data/wellknown
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/15-test_mp_rsa_data/plain_text
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/15-test_rsaoaep_data/plain_text
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/20-test_dhparam_data/pkcs3-2-1024.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/20-test_dhparam_data/pkcs3-2-2048.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/20-test_dhparam_data/pkcs3-5-1024.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/20-test_dhparam_data/x942-0-1024.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/25-test_eai_data/san.ascii
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/25-test_eai_data/san.utf8
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/25-test_pkcs7_data/malformed.pkcs7
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/25-test_rusext_data/grfc.msb
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/25-test_rusext_data/grfc.utf8
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/DH.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/DH.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/DSA.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/DSA.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/EC.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/EC.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/ED25519.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/ED25519.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/ED448.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/ED448.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/RSA.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/RSA.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/X25519.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/X25519.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/X448.priv.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/30-test_evp_pkey_provided/X448.pub.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_client_data/client.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_client_data/client.csr
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_client_data/client.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_client_data/server.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_client_data/server.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_msg_data/new.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_msg_data/pkcs10.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_msg_data/server.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/EndEntity1.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/EndEntity2.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/Intermediate_CA.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/IP_PBM.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/IR_protected.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/IR_unprotected.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/Root_CA.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_protect_data/server.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_server_data/CR_protected_PBM_1234.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/client.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/EndEntity1.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/EndEntity2.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/Intermediate_CA.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/IR_protected_0_extraCerts.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/IR_protected_2_extraCerts.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/IR_protected.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/IR_rmprotection.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/IR_unprotected.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/Root_CA.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/server.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/65-test_cmp_vfy_data/server.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_ca_data/revoked.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/big_issuing.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/big_root.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/big_server.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/big_trusted.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/issuing.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/issuing_expired.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/new.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/new_pass_12345.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/new_pub.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/random.bin
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/root.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/root_expired.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/server.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/server.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/signer.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/signer_issuing.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/signer.key
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/signer_only.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/signer.p12
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/signer_root.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/Mock/trusted.crt
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/test_commands.csv
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/test_connection.csv
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/test_credentials.csv
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/test_enrollment.csv
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmp_http_data/test_verification.csv
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cmsapi_data/encryptedData.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cms_data/bad_signtime_attr.cms
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cms_data/ciphertext_from_1_1_1.cms
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cms_data/ct_multiple_attr.cms
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cms_data/no_ct_attr.cms
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_cms_data/no_md_attr.cms
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_tsa_data/all-zero.tsq
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/80-test_tsa_data/sectigo-all-zero.tsr
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/90-test_store_data/testrsa.msb
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/90-test_store_data/testrsa.pvk
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check_data/dsapub_noparam.der
+CryptoPkg/Library/OpensslLib/openssl/test/recipes/ocsp-response.der
+CryptoPkg/Library/OpensslLib/openssl/test/shibboleth.pfx
+CryptoPkg/Library/OpensslLib/openssl/test/smcont.bin
+CryptoPkg/Library/OpensslLib/openssl/test/smime-eml/SignedInvalidMappingFromanyPolicyTest7.eml
+CryptoPkg/Library/OpensslLib/openssl/test/ssl-tests/protocol_version.pm
+CryptoPkg/Library/OpensslLib/openssl/test/ssl-tests/ssltests_base.pm
+CryptoPkg/Library/OpensslLib/openssl/test/ssl_test.tmpl
+CryptoPkg/Library/OpensslLib/openssl/test/testrsa_withattrs.der
+CryptoPkg/Library/OpensslLib/openssl/util/check-malloc-errs
+CryptoPkg/Library/OpensslLib/openssl/util/engines.num
+CryptoPkg/Library/OpensslLib/openssl/util/err-to-raise
+CryptoPkg/Library/OpensslLib/openssl/util/find-doc-nits
+CryptoPkg/Library/OpensslLib/openssl/util/find-unused-errs
+CryptoPkg/Library/OpensslLib/openssl/util/fix-deprecation
+CryptoPkg/Library/OpensslLib/openssl/util/fix-includes
+CryptoPkg/Library/OpensslLib/openssl/util/fix-includes.sed
+CryptoPkg/Library/OpensslLib/openssl/util/indent.pro
+CryptoPkg/Library/OpensslLib/openssl/util/libcrypto.num
+CryptoPkg/Library/OpensslLib/openssl/util/libssl.num
+CryptoPkg/Library/OpensslLib/openssl/util/markdownlint.rb
+CryptoPkg/Library/OpensslLib/openssl/util/merge-err-lines
+CryptoPkg/Library/OpensslLib/openssl/util/other-internal.syms
+CryptoPkg/Library/OpensslLib/openssl/util/other.syms
+CryptoPkg/Library/OpensslLib/openssl/util/perl/**/*.pm
+CryptoPkg/Library/OpensslLib/openssl/util/providers.num
+CryptoPkg/Library/OpensslLib/openssl/util/write-man-symlinks
+CryptoPkg/Library/OpensslLib/openssl/VERSION.dat
+CryptoPkg/Library/OpensslLib/openssl/VMS/engine.opt
+CryptoPkg/Library/OpensslLib/openssl/VMS/msg_install.com
+CryptoPkg/Library/OpensslLib/openssl/VMS/msg_staging.com
+CryptoPkg/Library/OpensslLib/openssl/VMS/test-includes.com
+CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/CreateTestCerts.cmd
+CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/SignFirmwareWithEKUs.cmd
+debian/**
 EmulatorPkg/Unix/.gdbinit
-EmulatorPkg/Unix/GdbRun
 EmulatorPkg/Unix/Host/X11IncludeHack
 EmulatorPkg/Unix/lldbinit
 EmulatorPkg/Win/VS2017/Win.vcxproj
 EmulatorPkg/Win/VS2017/Win.vcxproj.filters
 EmulatorPkg/Win/VS2017/Win.vcxproj.user
-IntelFspWrapperPkg/FspWrapperSecCore/Vtf0/Bin/ResetVec.ia32.raw
-StandaloneMmPkg
-StdLib/Efi/StdLib/etc/host.conf
-StdLib/Efi/StdLib/etc/hosts
-StdLib/Efi/StdLib/etc/networks
-StdLib/Efi/StdLib/etc/protocols
-StdLib/Efi/StdLib/etc/resolv.conf
-StdLib/Efi/StdLib/etc/services
-StdLib/LibC/Softfloat/bits32/softfloat-macros
-StdLib/LibC/Softfloat/bits64/softfloat-macros
-StdLib/LibC/Softfloat/softfloat-specialize
-StdLib/LibC/Softfloat/templates/softfloat-specialize
+.git/**
+.git-blame-ignore-revs
+.github/codeql/edk2.qls
+.gitmodules
+IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
+**/*.json
+.mailmap
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/bootstrap
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/BUILD
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/compiler_config_setting.bzl
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/docs/brotli.svg
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/python/_brotli.cc
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/scripts/sources.lst
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/setup.cfg
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/tests/testdata/empty
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/tests/testdata/empty.compressed
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/tests/testdata/ukkonooa
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/tests/testdata/ukkonooa.compressed
+MdeModulePkg/Library/BrotliCustomDecompressLib/brotli/WORKSPACE
+MdePkg/Library/MipiSysTLib/mipisyst/CODEOWNERS
+MdePkg/Library/MipiSysTLib/mipisyst/collateral/sys-t_1-0.xsd
+MdePkg/Library/MipiSysTLib/mipisyst/.gitmodules
+MdePkg/Library/MipiSysTLib/mipisyst/library/doxygen/mipi_sys_t_library_flow.vsd
+OvmfPkg/AmdSev/Grub/grub.cfg
+.pytool/Plugin/UncrustifyCheck/uncrustify.cfg
+ReadMe.rst
+RedfishPkg/Documents/Media/BmcExposedUsbNic.svg
+RedfishPkg/Documents/Media/EmualtorPlatformLibrary.svg
+RedfishPkg/Documents/Media/PlatformWihtBmcLibrary.svg
+RedfishPkg/Documents/Media/RedfishDriverStack.svg
+RedfishPkg/Library/JsonLib/Readme.rst
+**/*.yaml
+**/*.yml
index 0d6c47fbde2a6f0739ecb0937de53313f2ceb7b4..76513016624cdfc6f369ede1e7608c52a2325e2c 100644 (file)
@@ -1,44 +1,5 @@
 ArmPkg/Library/GccLto/liblto-aarch64.a
 ArmPkg/Library/GccLto/liblto-arm.a
-BaseTools/Bin/CYGWIN_NT-5.1-i686/BootSectImage
-BaseTools/Bin/CYGWIN_NT-5.1-i686/BuildEnv
-BaseTools/Bin/CYGWIN_NT-5.1-i686/Ecc
-BaseTools/Bin/CYGWIN_NT-5.1-i686/EfiLdrImage
-BaseTools/Bin/CYGWIN_NT-5.1-i686/EfiRom
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenCrc32
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenDepex
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenFds
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenFfs
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenFv
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenFw
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenPage
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenSec
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GenVtf
-BaseTools/Bin/CYGWIN_NT-5.1-i686/GnuGenBootSector
-BaseTools/Bin/CYGWIN_NT-5.1-i686/LzmaCompress
-BaseTools/Bin/CYGWIN_NT-5.1-i686/LzmaF86Compress
-BaseTools/Bin/CYGWIN_NT-5.1-i686/RunBinToolFromBuildDir
-BaseTools/Bin/CYGWIN_NT-5.1-i686/RunToolFromSource
-BaseTools/Bin/CYGWIN_NT-5.1-i686/Split
-BaseTools/Bin/CYGWIN_NT-5.1-i686/TargetTool
-BaseTools/Bin/CYGWIN_NT-5.1-i686/TianoCompress
-BaseTools/Bin/CYGWIN_NT-5.1-i686/Trim
-BaseTools/Bin/CYGWIN_NT-5.1-i686/VfrCompile
-BaseTools/Bin/CYGWIN_NT-5.1-i686/VolInfo
-BaseTools/Bin/CYGWIN_NT-5.1-i686/build
-BaseTools/Bin/Darwin-i386/Arm/DEBUG_XCODE31/CompilerIntrinsicsLib.lib
-BaseTools/Bin/Darwin-i386/Arm/DEBUG_XCODE32/CompilerIntrinsicsLib.lib
-BaseTools/Bin/Darwin-i386/Arm/RELEASE_XCODE31/CompilerIntrinsicsLib.lib
-BaseTools/Bin/Darwin-i386/Arm/RELEASE_XCODE32/CompilerIntrinsicsLib.lib
 BaseTools/Source/Python/Eot/EfiCompressor.pyd
 BaseTools/Source/Python/Eot/LzmaCompressor.pyd
 IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/IA32/ResetVector.ia32.port80.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/IA32/ResetVector.ia32.serial.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/IA32/ResetVector.ia32.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/X64/PageTable2M/ResetVector.x64.port80.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/X64/PageTable2M/ResetVector.x64.serial.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/X64/PageTable2M/ResetVector.x64.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/X64/PageTable1G/ResetVector.x64.port80.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/X64/PageTable1G/ResetVector.x64.serial.raw
-UefiCpuPkg/ResetVector/Vtf0/Bin/X64/PageTable1G/ResetVector.x64.raw
index 2f25a6548522d396119f05a6eb8def2017412ead..61b93c09050bab00644b4e90675ef43a8b150ae7 100644 (file)
@@ -1,3 +1,81 @@
+pve-edk2-firmware (4.2023.08-4) bookworm; urgency=medium
+
+  * fix CVE-2023-48733: disable EFI shell in SB mode
+
+ -- Proxmox Support Team <support@proxmox.com>  Thu, 15 Feb 2024 08:56:32 +0100
+
+pve-edk2-firmware (4.2023.08-3) bookworm; urgency=medium
+
+  * fixes for "PixieFAIL" PXE vulnerabilities
+    - CVE-2023-45229 to CVE-2023-45237
+
+ -- Proxmox Support Team <support@proxmox.com>  Wed, 17 Jan 2024 09:00:02 +0100
+
+pve-edk2-firmware (4.2023.08-2) bookworm; urgency=medium
+
+  * enable deprecated PVSCSI support again for backwards compatibility
+
+ -- Proxmox Support Team <support@proxmox.com>  Fri, 24 Nov 2023 13:57:33 +0100
+
+pve-edk2-firmware (4.2023.08-1) bookworm; urgency=medium
+
+  * update to edk2-stable202308
+
+  * switch to shorter and easier to read version format
+
+  * ship 2MB builds via legacy 2023.02 versions, as upstream dropped support
+    for them, to avoid breakage
+
+  * split out ARM64 build into separate package
+
+  * add RISC-V build as separate package
+
+ -- Proxmox Support Team <support@proxmox.com>  Tue, 07 Nov 2023 16:19:26 +0100
+
+pve-edk2-firmware (3.20230228-4) bookworm; urgency=medium
+
+  * limiting the phys-bits to 46 instead of 47 to work around older guest
+    kernel bug, e.g., kernel 4.15 on Ubuntu 18.04.
+
+ -- Proxmox Support Team <support@proxmox.com>  Tue, 06 Jun 2023 16:06:21 +0200
+
+pve-edk2-firmware (3.20230228-3) bookworm; urgency=medium
+
+  * re-build for Proxmox VE 8 / Debian Bookworm
+
+  * fix empty AAVMF_VARS.fd file
+
+  * fix #4696: Revert "ArmVirtPkg: make EFI_LOADER_DATA non-executable" until
+    GRUB fixes are more generally available.
+
+ -- Proxmox Support Team <support@proxmox.com>  Wed, 24 May 2023 10:53:40 +0200
+
+pve-edk2-firmware (3.20230228-2) bullseye; urgency=medium
+
+  * fix #4625: restore SMBIOS type 0 table defaults
+
+ -- Proxmox Support Team <support@proxmox.com>  Tue, 04 Apr 2023 16:11:23 +0200
+
+pve-edk2-firmware (3.20230228-1) bullseye; urgency=medium
+
+  * update sources to upstream edk2-stable202302 tag
+
+ -- Proxmox Support Team <support@proxmox.com>  Fri, 24 Mar 2023 09:21:50 +0100
+
+pve-edk2-firmware (3.20221111-2) bullseye; urgency=medium
+
+  * d/rules: re-enable PVSCSI support
+
+ -- Proxmox Support Team <support@proxmox.com>  Thu, 23 Mar 2023 11:25:08 +0100
+
+pve-edk2-firmware (3.20221111-1) bullseye; urgency=medium
+
+  * update sources to upstream edk2-stable202211 tag
+
+  * sync in some packaging updates from Debian
+
+ -- Proxmox Support Team <support@proxmox.com>  Tue, 07 Mar 2023 10:04:21 +0100
+
 pve-edk2-firmware (3.20220526-1) bullseye; urgency=medium
 
   * update sources to upstream edk2-stable202205 tag
index 8d642cd053550fb713e05f438d815895812b50b4..27e3a0f3fc0758a54989b66a2c5524c15c207d10 100644 (file)
@@ -3,30 +3,76 @@ Section: misc
 Priority: optional
 Maintainer: Proxmox Support Team <support@proxmox.com>
 Build-Depends: bc,
- debhelper-compat (= 12),
- dosfstools,
- dpkg (>= 1.19.3),
- gcc-aarch64-linux-gnu,
- gcc-multilib [i386],
- iasl,
- mtools,
- nasm,
- python3,
- python3-distutils,
- python3-pexpect,
- qemu-utils,
- pve-qemu-kvm | qemu-system-x86 (>= 1:2.12+dfsg),
- uuid-dev,
- xorriso,
+               debhelper-compat (= 12),
+               dosfstools,
+               dpkg (>= 1.19.3),
+               gcc-aarch64-linux-gnu,
+               gcc-multilib [i386],
+               gcc-riscv64-linux-gnu,
+               iasl,
+               mtools,
+               nasm,
+               pve-qemu-kvm | qemu-system-arm (>= 1:2.12+dfsg),
+               pve-qemu-kvm | qemu-system-x86 (>= 1:2.12+dfsg),
+               python3,
+               python3-distutils,
+               python3-pexpect,
+               qemu-utils,
+               uuid-dev,
+               xorriso,
 Standards-Version: 4.5.0
 Homepage: http://www.tianocore.org
 XS-Build-Indep-Architecture: amd64
 
 Package: pve-edk2-firmware
 Architecture: all
-Depends: ${misc:Depends}
+Depends: pve-edk2-firmware-legacy, pve-edk2-firmware-ovmf, ${misc:Depends},
 Multi-Arch: foreign
 Description: edk2 based UEFI firmware modules for virtual machines
  Open Virtual Machine Firmware is a build of EDK II for 64-bit, 32-bit x86
- and 64-bit ARM virtual machines. It includes full support for UEFI, including
- Secure Boot, allowing use of UEFI in place of a traditional BIOS in your VM.
+ virtual machines. It includes full support for UEFI, including Secure Boot,
+ allowing use of UEFI in place of a traditional BIOS in your VM.
+ Meta package depending on OVMF and Legacy OVMF images to ease the upgrade
+ transition.
+
+Package: pve-edk2-firmware-ovmf
+Architecture: all
+Depends: ${misc:Depends},
+Breaks: pve-edk2-firmware (<< 4.2023.08-1),
+Multi-Arch: foreign
+Description: edk2 based UEFI firmware modules for virtual machines
+ Open Virtual Machine Firmware is a build of EDK II for 64-bit, 32-bit x86
+ virtual machines. It includes full support for UEFI, including Secure Boot,
+ allowing use of UEFI in place of a traditional BIOS in your VM.
+
+Package: pve-edk2-firmware-aarch64
+Architecture: all
+Depends: ${misc:Depends},
+Breaks: pve-edk2-firmware (<< 4.2023.08-1),
+Multi-Arch: foreign
+Description: edk2 based ARM64 UEFI firmware modules for virtual machines
+ A build of EDK II for 64-bit ARM virtual machines. It includes full support
+ for UEFI, including Secure Boot, allowing use of UEFI in place of a
+ traditional BIOS in your VM.
+
+Package: pve-edk2-firmware-riscv
+Architecture: all
+Depends: ${misc:Depends},
+Multi-Arch: foreign
+Description: edk2 based RISC-V UEFI firmware modules for virtual machines
+ A build of EDK II for 64-bit RISC-V virtual machines. It includes full support
+ for UEFI, including Secure Boot, allowing use of UEFI in place of a
+ traditional BIOS in your VM.
+
+Package: pve-edk2-firmware-legacy
+Architecture: all
+Depends: ${misc:Depends},
+Breaks: pve-edk2-firmware (<< 4.2023.08-1),
+Multi-Arch: foreign
+Description: edk2 based legacy 2MB UEFI firmware modules for virtual machines
+ Open Virtual Machine Firmware is a build of EDK II for 64-bit, 32-bit x86
+ virtual machines. It includes full support for UEFI, including Secure Boot,
+ allowing use of UEFI in place of a traditional BIOS in your VM.
+ This packages includes a static build of legacy images that got dropped from
+ upstream because the small size results in to many limitations, but Proxmox VE
+ still needs to provide backward compat for older VMs.
index 29134b9c23eac2a532aea7a28fb6ca982067d6bc..5d7cbf25b2e96ec59ef42e5acb0d49eb1179dcf1 100644 (file)
@@ -5,54 +5,21 @@ Source: git://github.com/tianocore/edk2.git, http://www.openssl.org/source/,
  See get-orig-source in debian/rules for details.
 
 Files: *
-Copyright: 1999-2013, Intel Corporation
-License: BSD-2-clause
-
-Files: StdLib/PosixLib/Stringlist/stringlist.c StdLib/PosixLib/Gen/dirname.c
-       StdLib/LibC/Time/strptime.c StdLib/LibC/Locale/aliasname_local.h
-       StdLib/LibC/Locale/wcsxfrm.c StdLib/LibC/Locale/wcstold.c
-       StdLib/LibC/Locale/__mb_cur_max.c StdLib/LibC/Locale/_wcstod.h
-       StdLib/LibC/Locale/aliasname.c StdLib/LibC/Locale/__wctoint.h
-       StdLib/LibC/Locale/wcsftime.c StdLib/LibC/Locale/wcscoll.c
-       StdLib/LibC/Locale/wcstof.c StdLib/LibC/Locale/wcstod.c
-       StdLib/LibC/Locale/wcstoul.c StdLib/LibC/Locale/setlocale32.c
-       StdLib/LibC/Math/* StdLib/LibC/gdtoa/* StdLib/LibC/StdLib/setprogname.c
-       StdLib/Include/strings.h StdLib/Include/Ipf/* StdLib/Include/nsswitch.h
-       StdLib/Include/stringlist.h StdLib/BsdSocketLib/getnetnamadr.c
-       StdLib/BsdSocketLib/getnetbynis.c StdLib/BsdSocketLib/gethostnamadr.c
-       StdLib/BsdSocketLib/gethostbynis.c
-Copyright: 1993, Sun Microsystems, Inc.
-           1994, Garrett Wollman
-           1994-2008, The NetBSD Foundation, Inc.
-           1994-1996, Carnegie-Mellon University
-           1996-1997 John D. Polstra
-           1998-2000, Lucent Technologies
-           1998-2001, Doug Rabson
-           1999-2006, Citrus Project
-           1999-2012, Intel Corporation
-           2002, YAMAMOTO Takashi
-           2002, Tim J. Robbins
-           2002-2004, Marcel Moolenaar
-           2003, David Schultz <das@FreeBSD.ORG>
-License: BSD-2-clause
-
-Files: OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.*
-Copyright: 2004-2013, Intel Corporation
-           2012, Ashley DeSimone
-License: BSD-2-clause
+Copyright: 2019, TianoCore and contributors.  All rights reserved.
+License: BSD-2-Clause-Patent
 
 Files: OvmfPkg/*
-Copyright: 2004-2013, Intel Corporation
+Copyright: 2004-2019, Intel Corporation
            2008-2009, Apple Inc.
            2011, Andrei Warkentin <andreiw@motorola.com>
            2011-2012, Bei Guan <gbtju85@gmail.com>
            2012-2013, Red Hat, Inc
            2013, ARM Ltd.
-License: BSD-2-clause
+License: BSD-2-Clause-Patent
 
 Files: BaseTools/Source/C/GenFw/elf*.h
-       BaseTools/Source/Python/sitecustomize.py DuetPkg/build*.sh
-       EmulatorPkg/* MdeModulePkg/Core/DxeIplPeim/Arm/DxeLoadFunc.c
+       BaseTools/Source/Python/sitecustomize.py EmulatorPkg/*
+       MdeModulePkg/Core/DxeIplPeim/Arm/DxeLoadFunc.c
        MdeModulePkg/Library/PeiDebugPrintHobLib/PeiDebugPrintHobLib.c
        MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
        MdePkg/Include/* MdePkg/Library/*
@@ -62,7 +29,35 @@ Copyright: 1996-1998 John D. Polstra
            2008-2012, Apple Inc.
            2011-2013, ARM Limited
            2013, Red Hat, Inc.
-License: BSD-2-clause
+License: BSD-2-Clause-Patent
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/library/include/mipi_syst/api.h
+Copyright: 2018-2023, MIPI Alliance, Inc.
+License: BSD-3-clause
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/library/include/mipi_syst/message.h
+Copyright: 2018-2023, MIPI Alliance, Inc.
+License: BSD-3-clause
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/library/include/mipi_syst.h.in
+Copyright: 2018-2023, MIPI Alliance, Inc.
+License: BSD-3-clause
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/library/src/mipi_syst_api.c
+Copyright: 2018-2023, MIPI Alliance, Inc.
+License: BSD-3-clause
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/library/test/unit/mipi_syst_sbd_test.cpp
+Copyright: 2018-2023, MIPI Alliance, Inc.
+License: BSD-3-clause
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/library/src/mipi_syst_writer.c
+Copyright: 2018-2023, MIPI Alliance, Inc.
+License: BSD-3-clause
+
+Files: MdePkg/Library/MipiSysTLib/mipisyst/*
+Copyright: 2018, MIPI Alliance, Inc.
+License: BSD-3-clause
 
 Files: ArmPkg/* ArmPlatformPkg/* BaseTools/Source/C/Common/*PeCoff*.c
        BaseTools/Source/C/GenFv/GenFvInternalLib.c
@@ -77,138 +72,15 @@ Copyright: 2011-2013, ARM Limited
            2009, Hewlett-Packard Company
            2011, Hewlett-Packard Corporation
            2003-2008 University of Illinois at Urbana-Champaign
-License: BSD-2-clause
+License: BSD-2-Clause-Patent
 
 Files: ShellPkg/Application/Shell/* ShellPkg/Library/*
 Copyright: 1999-2013, Intel Corporation
            2013, Hewlett-Packard Development Company, L.P.
-License: BSD-2-clause
-
-Files: ArmPkg/Library/CompilerIntrinsicsLib/AArch64/memcpy.S
-       ArmPlatformPkg/ArmVExpressPkg/Scripts/uefi-aarch64-bootstrap/*
-       EdkCompatibilityPkg/*
-       StdLibPrivateInternalFiles/Include/kfile.h StdLib/PosixLib/Glob/glob.c
-       StdLib/PosixLib/Gen/readdir.c StdLib/PosixLib/Gen/utime.c
-       StdLib/PosixLib/Gen/opendir.c StdLib/PosixLib/Gen/closedir.c
-       StdLib/LibC/Time/gettimeofday.c StdLib/LibC/Locale/_wcstol.h
-       StdLib/LibC/Locale/rune.h StdLib/LibC/Locale/setlocale.c
-       StdLib/LibC/Locale/iswctype_sb.c StdLib/LibC/Locale/_wcstoul.h
-       StdLib/LibC/Locale/multibyte_sb.c StdLib/LibC/Locale/runetype.h
-       StdLib/LibC/String/strncasecmp.c StdLib/LibC/Main/is*.c
-       StdLib/LibC/Main/*/is*.c StdLib/LibC/NetUtil/inet_*.c
-       StdLib/LibC/Stdio/* StdLib/LibC/StdLib/* StdLib/Include/netatalk/*
-       StdLib/Include/glob.h StdLib/Include/Ipf/machine/limits.h
-       StdLib/Include/Ipf/machine/int_types.h
-       StdLib/Include/Ipf/machine/param.h StdLib/Include/Ipf/machine/stdarg.h
-       StdLib/Include/Ipf/machine/types.h StdLib/Include/Ipf/machine/varargs.h
-       StdLib/Include/Ipf/machine/vmparam.h StdLib/Include/Ipf/machine/ansi.h
-       StdLib/Include/Ipf/machine/aout_machdep.h StdLib/Include/netinet6/in6.h
-       StdLib/Include/pwd.h StdLib/Include/locale.h StdLib/Include/dirent.h
-       StdLib/Include/arpa/nameser.h StdLib/Include/arpa/inet.h
-       StdLib/Include/utime.h StdLib/Include/netinet/in.h
-       StdLib/Include/netinet/tcp.h StdLib/Include/X64/machine/atomic.h
-       StdLib/Include/X64/machine/asm.h StdLib/Include/X64/machine/int_types.h
-       StdLib/Include/X64/machine/types.h StdLib/Include/X64/machine/ansi.h
-       StdLib/Include/paths.h StdLib/Include/netdb.h
-       StdLib/Include/Ia32/machine/asm.h StdLib/Include/Ia32/machine/int_types.h
-       StdLib/Include/Ia32/machine/param.h StdLib/Include/Ia32/machine/types.h
-       StdLib/Include/Ia32/machine/ansi.h StdLib/BsdSocketLib/getaddrinfo.c
-       StdLib/BsdSocketLib/getnameinfo.c
-Copyright: 1982-2013, Intel Corporation
-           1982-1994, The Regents of the University of California
-           1990-1991, Regents of The University of Michigan
-           1993-1994, Digital Equipment Corporation
-           1995, Jason Downs
-           1995-1997, Kungliga Tekniska Hogskolan
-           1995-1998, WIDE Project
-           1996-1999, Internet Software Consortium
-           1997, Todd C. Miller <Todd.Miller@courtesan.com>
-           2002, Wasabi Systems, Inc
-           2004, Internet Systems Consortium, Inc.
-           2010-2012, Intel Corporation
-           2011-2013, ARM Limited
-License: BSD-3-clause
-
-Files: StdLibPrivateInternalFiles/Include/namespace.h
-       StdLibPrivateInternalFiles/Include/reentrant.h
-       StdLibPrivateInternalFiles/Include/extern.h
-       StdLib/PosixLib/Err/warn_err.c StdLib/LibC/Time/timegm.c
-       StdLib/LibC/Time/strftime.c StdLib/LibC/Locale/ctypeio.*
-       StdLib/LibC/String/strsep.c StdLib/LibC/gdtoa/_strtold.c
-       StdLib/LibC/gdtoa/_strtof.c StdLib/LibC/Main/Arm/flt_rounds.c
-       StdLib/LibC/Uefi/writev.c StdLib/LibC/Uefi/select.c
-       StdLib/LibC/Uefi/compat.c StdLib/LibC/NetUtil/inet_addr.c
-       StdLib/LibC/Stdio/fparseln.c StdLib/LibC/Stdio/vswscanf.c
-       StdLib/LibC/Stdio/vfwscanf.c StdLib/LibC/Stdio/flockfile.c
-       StdLib/Include/sys/* StdLib/Include/x86/ieee.h
-       StdLib/Include/sysexits StdLib/Include/Ipf/machine/loadfile_machdep.h
-       StdLib/Include/Ipf/machine/cpu_counter.h
-       StdLib/Include/Ipf/machine/pmap.h
-       StdLib/Include/Ipf/machine/wchar_limits.h
-       StdLib/Include/Ipf/machine/cpu.h StdLib/Include/Ipf/machine/disklabel.h
-       StdLib/Include/Ipf/machine/ptrace.h StdLib/Include/Ipf/machine/setjmp.h
-       StdLib/Include/Ipf/machine/int_limits.h StdLib/Include/nl_types.h
-       StdLib/Include/Arm/machine/* StdLib/Include/net/*
-       StdLib/Include/inttypes.h StdLib/Include/arpa/telnet.h
-       StdLib/Include/arpa/nameser_compat.h StdLib/Include/arpa/ftp.h
-       StdLib/Include/netinet/ip.h StdLib/Include/netinet/in_systm.h
-       StdLib/Include/*/machine/int_mwgwtypes.h
-       StdLib/Include/*/machine/int_const.h
-       StdLib/Include/X64/machine/byte_swap.h
-       StdLib/Include/*/machine/int_fmtio.h
-       StdLib/Include/X64/machine/int_limits.h StdLib/Include/resolv.h
-       StdLib/Include/netns/ns.h StdLib/Include/Ia32/machine/byte_swap.h
-       StdLib/Include/Ia32/machine/int_limits.h StdLib/BsdSocketLib/map_v4v6.c
-       StdLib/BsdSocketLib/inet_net_pton.c StdLib/BsdSocketLib/res_*.c
-       StdLib/BsdSocketLib/sethostname.c StdLib/BsdSocketLib/ns_*.c
-       StdLib/BsdSocketLib/getnetbyht.c StdLib/BsdSocketLib/getproto.c
-       StdLib/BsdSocketLib/gethostname.c StdLib/BsdSocketLib/gethostbydns.c
-       StdLib/BsdSocketLib/herror.c StdLib/BsdSocketLib/getprotoname.c
-       StdLib/BsdSocketLib/inet_neta.c StdLib/BsdSocketLib/getservbyport.c
-       StdLib/BsdSocketLib/inet_pton.c StdLib/BsdSocketLib/getservent.c
-       StdLib/BsdSocketLib/gethostbyht.c StdLib/BsdSocketLib/getservbyname.c
-       StdLib/BsdSocketLib/getnetbydns.c StdLib/BsdSocketLib/getprotoent.c
-Copyright: 1983-1993, Digital Equipment Corporation
-           1982-1994, Regents of the University of California
-           1988, University of Utah
-           1993, Carlos Leandro and Rui Salgueiro
-           1994, Christopher G. Demetriou
-           1994, Winning Strategies, Inc
-           1994-1997, Mark Brinicombe
-           1996, Internet Software Consortium
-           1996-1997, Christos Zoulas
-           1997-2006, The NetBSD Foundation, Inc
-           1998 HD Associates, Inc
-           2000-2001, Artur Grabowski <art@openbsd.org>
-           1999-2012, Intel Corporation
-License: BSD-4-clause
-
-Files: StdLib/LibC/Stdio/fileext.h StdLib/LibC/Stdio/wscanf.c
-       StdLib/LibC/Stdio/vwscanf.c StdLib/LibC/Stdio/*wc.c
-       StdLib/LibC/Stdio/*wchar.c StdLib/LibC/Stdio/fgetws.c
-       StdLib/LibC/Stdio/swscanf.c StdLib/LibC/Stdio/wcio.h
-       StdLib/LibC/Stdio/fwide.c StdLib/LibC/Stdio/fwscanf.c
-       StdLib/LibC/Stdio/wprintf.c StdLib/LibC/Stdio/swprintf.c
-       StdLib/LibC/Stdio/fputws.c StdLib/LibC/Stdio/vwprintf.c
-       StdLib/LibC/Stdio/fwprintf.c
-Copyright: 2001, Citrus Project
-           2002, Tim J. Robbins
-           2010-2012, Intel Corporation
-License: BSD-2-clause
+License: BSD-2-Clause-Patent
 
-Files: StdLib/LibC/String/strlcat.c StdLib/LibC/String/strlcpy.c
-       StdLib/LibC/NetUtil/inet_ntop.c StdLib/BsdSocketLib/base64.c
-       StdLib/BsdSocketLib/inet_net_ntop.c StdLib/BsdSocketLib/res_data.c
-       StdLib/BsdSocketLib/ns_netint.c StdLib/BsdSocketLib/nsap_addr.c
-Copyright: 1998, Todd C. Miller <Todd.Miller@courtesan.com>
-           1996-1999, Internet Software Consortium
-           1995-2000, International Business Machines, Inc
-           2004, Internet Systems Consortium, Inc.
-           2011, Intel Corporation
-License: ISC
-
-Files: CryptoPkg/Library/OpensslLib/openssl-0.9.8w/*
-Copyright: 1998-2004 The OpenSSL Project
+Files: CryptoPkg/Library/OpensslLib/openssl/*
+Copyright: 1998-2019 The OpenSSL Project
            1995-1998 Eric A. Young, Tim J. Hudson
 License: OpenSSL
 
@@ -216,58 +88,81 @@ Files: debian/tests/shell.py
 Copyright: 2019 Canonical Ltd.
 License: GPL-3
 
-License: BSD-2-clause
+License: BSD-2-Clause-Patent
  Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
+ modification, are permitted provided that the following conditions are met:
+ .
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
  .
- * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
+ Subject to the terms and conditions of this license, each copyright holder
+ and contributor hereby grants to those receiving rights under this license
+ a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except for failure to satisfy the conditions of this license) patent
+ license to make, have made, use, offer to sell, sell, import, and otherwise
+ transfer this software, where such license applies only to those patent
+ claims, already acquired or hereafter acquired, licensable by such copyright
+ holder or contributor that are necessarily infringed by:
  .
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ (a) their Contribution(s) (the licensed copyrights of copyright holders and
+     non-copyrightable additions of contributors, in source or binary form)
+     alone; or
+ .
+ (b) combination of their Contribution(s) with the work of authorship to
+     which such Contribution(s) was added by such copyright holder or
+     contributor, if, at the time the Contribution is added, such addition
+     causes such combination to be necessarily infringed. The patent license
+     shall not apply to any other combinations which include the
+     Contribution.
+ .
+ Except as expressly stated above, no rights or licenses from any copyright
+ holder or contributor is granted under this license, whether expressly, by
+ implication, estoppel or otherwise.
+ .
+ DISCLAIMER
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
 
 License: BSD-3-clause
  Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
+ modification, are permitted provided that the following conditions are met:
  .
-   . Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
  .
-   . Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
  .
  . Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
  .
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
 
 License: BSD-4-clause
  Redistribution and use in source and binary forms, with or without
index f9328c1710725c4176a58f2bb52fffe07aea5217..3a5aafd2a8bc1fc60a0584153eba01220826e77c 100755 (executable)
@@ -53,6 +53,11 @@ if __name__ == '__main__':
         help='UEFI code image',
         required=True,
     )
+    parser.add_argument(
+        "--no-default",
+        action="store_true",
+        help='Do not enroll the default keys, just the PK/KEK1 certificate',
+    )
     parser.add_argument(
         "-V", "--vars-template",
         help='UEFI vars template',
@@ -117,13 +122,19 @@ if __name__ == '__main__':
     child = pexpect.spawn(' '.join(q.command))
     if args.debug:
         child.logfile = sys.stdout.buffer
-    child.expect(['Press .* or any other key to continue'], timeout=60)
+    child.expect(['Press .* or any other key to continue'], timeout=None)
     child.sendline('\x1b')
-    child.expect(['Shell> '])
+    child.expect(['Shell> '], timeout=None)
     child.sendline('FS0:\r')
-    child.expect(['FS0:\\\\> '])
-    child.sendline('EnrollDefaultKeys.efi\r')
-    child.expect(['FS0:\\\\> '])
+    child.expect(['FS0:\\\\> '], timeout=None)
+    enrollcmd = ['EnrollDefaultKeys.efi']
+    if args.no_default:
+        enrollcmd.append("--no-default")
+    child.sendline(f'{" ".join(enrollcmd)}\r')
+    child.expect(['FS0:\\\\> '], timeout=None)
+    # Clear the BootOrder. See #1015759
+    child.sendline('setvar BootOrder =\r')
+    child.expect(['FS0:\\\\> '], timeout=None)
     child.sendline('reset -s\r')
     child.wait()
     shutil.copy(q.pflash.varfile_path, args.out_file)
index b3f3ddecf8e214dfb06b597be4b737dcb2b689cc..b5774394791774abd1433ade7c57f3ca1d6235b6 100644 (file)
@@ -2,9 +2,10 @@
 
 # Use heuristics to identify new files that maybe binaries.
 # Flagged files need to be manually inspected and either added to the
-# allow list (because they are safe to redistribute), or to the reject list
+# ignore list (because they are safe to redistribute), or to the reject list
 # (so that they'll be removed prior to orig.tar.xz generation).
 
+import glob
 import os
 import re
 import sys
@@ -41,15 +42,26 @@ def extensionOK(name):
 
 
 if __name__ == '__main__':
+    ret = 0
     top = './'
-    for root, dirs, files in os.walk(top):
-        with open('./debian/binary-check.allow', 'r') as f:
-            allowlist = list(map(lambda s: s.strip(), f.readlines()))
 
-        ret = 0
+    ignorelist = []
+    with open('./debian/binary-check.ignore', 'r') as f:
+        ignoreglobs = list(map(lambda s: s.strip(), f.readlines()))
+    for pattern in ignoreglobs:
+        matches = glob.glob(pattern, recursive=True, include_hidden=True)
+        if len(matches) == 0:
+            print(
+                f"WARNING: pattern {pattern} matched no files.",
+                file=sys.stderr,
+            )
+        ignorelist += matches
+
+    for root, dirs, files in os.walk(top):
         for name in files:
             relpath = os.path.join(root, name)[len(top):]
-            if relpath in allowlist:
+            if relpath in ignorelist:
+                print(f"Ignoring: {relpath}", file=sys.stderr)
                 continue
             if nameOK(name):
                 continue
diff --git a/debian/legacy-2M-builds/OVMF_CODE.fd b/debian/legacy-2M-builds/OVMF_CODE.fd
new file mode 100644 (file)
index 0000000..ab81b1c
Binary files /dev/null and b/debian/legacy-2M-builds/OVMF_CODE.fd differ
diff --git a/debian/legacy-2M-builds/OVMF_CODE.secboot.fd b/debian/legacy-2M-builds/OVMF_CODE.secboot.fd
new file mode 100644 (file)
index 0000000..abb1123
Binary files /dev/null and b/debian/legacy-2M-builds/OVMF_CODE.secboot.fd differ
diff --git a/debian/legacy-2M-builds/OVMF_VARS.fd b/debian/legacy-2M-builds/OVMF_VARS.fd
new file mode 100644 (file)
index 0000000..3b8bb9b
Binary files /dev/null and b/debian/legacy-2M-builds/OVMF_VARS.fd differ
diff --git a/debian/legacy-2M-builds/OVMF_VARS.ms.fd b/debian/legacy-2M-builds/OVMF_VARS.ms.fd
new file mode 100644 (file)
index 0000000..cb9b25b
Binary files /dev/null and b/debian/legacy-2M-builds/OVMF_VARS.ms.fd differ
diff --git a/debian/patches/ArmVirtPkg-disable-the-EFI_MEMORY_ATTRIBUTE-protocol.patch b/debian/patches/ArmVirtPkg-disable-the-EFI_MEMORY_ATTRIBUTE-protocol.patch
new file mode 100644 (file)
index 0000000..f5302ea
--- /dev/null
@@ -0,0 +1,58 @@
+Description: ArmVirtPkg: Disable the EFI memory attributes protocol
+ Temporarily disable the EFI_MEMORY_ATTRIBUTE_PROTOCOL to workaround
+ a bug in shim until distributions have had a chance to fix it.
+Author: dann frazier <dannf@debian.org>
+Bug-Debian: https://bugs.debian.org/1042438
+Bug-Ubuntu: https://launchpad.net/bugs/2036604
+Last-Update: 2023-09-23
+
+Index: edk2-2023.05/ArmPkg/Drivers/CpuDxe/CpuDxe.c
+===================================================================
+--- edk2-2023.05.orig/ArmPkg/Drivers/CpuDxe/CpuDxe.c
++++ edk2-2023.05/ArmPkg/Drivers/CpuDxe/CpuDxe.c
+@@ -244,8 +244,6 @@ CpuDxeInitialize (
+                   &mCpuHandle,\r
+                   &gEfiCpuArchProtocolGuid,\r
+                   &mCpu,\r
+-                  &gEfiMemoryAttributeProtocolGuid,\r
+-                  &mMemoryAttribute,\r
+                   NULL\r
+                   );\r
\r
+Index: edk2-2023.05/ArmPkg/Drivers/CpuDxe/CpuDxe.h
+===================================================================
+--- edk2-2023.05.orig/ArmPkg/Drivers/CpuDxe/CpuDxe.h
++++ edk2-2023.05/ArmPkg/Drivers/CpuDxe/CpuDxe.h
+@@ -30,12 +30,9 @@
+ #include <Protocol/Cpu.h>\r
+ #include <Protocol/DebugSupport.h>\r
+ #include <Protocol/LoadedImage.h>\r
+-#include <Protocol/MemoryAttribute.h>\r
\r
+ extern BOOLEAN  mIsFlushingGCD;\r
\r
+-extern EFI_MEMORY_ATTRIBUTE_PROTOCOL  mMemoryAttribute;\r
+-\r
+ /**\r
+   This function registers and enables the handler specified by InterruptHandler for a processor\r
+   interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the\r
+Index: edk2-2023.05/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+===================================================================
+--- edk2-2023.05.orig/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
++++ edk2-2023.05/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+@@ -23,7 +23,6 @@
+   CpuDxe.h\r
+   CpuMmuCommon.c\r
+   Exception.c\r
+-  MemoryAttribute.c\r
\r
+ [Sources.ARM]\r
+   Arm/Mmu.c\r
+@@ -54,7 +53,6 @@
\r
+ [Protocols]\r
+   gEfiCpuArchProtocolGuid\r
+-  gEfiMemoryAttributeProtocolGuid\r
\r
+ [Guids]\r
+   gEfiDebugImageInfoTableGuid\r
diff --git a/debian/patches/CVE-2023-45229_45237.patch b/debian/patches/CVE-2023-45229_45237.patch
new file mode 100644 (file)
index 0000000..53dc806
--- /dev/null
@@ -0,0 +1,7277 @@
+From 0cf3620092c1f5d2093e5bfa43ff137b888f18b3 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 15 Dec 2023 11:24:43 -0800
+Subject: [PATCH 01/12] SECURITY PATCH TCBZ4535 - CVE-2023-45230 - Patch
+
+---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h    |  39 +++
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.c      | 411 +++++++++++++++++---------
+ NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 455 +++++++++++++++++++++--------
+ NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h |  82 +++---
+ 4 files changed, 707 insertions(+), 280 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+index 0eb9c669b5..b552331767 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+@@ -45,6 +45,45 @@ typedef struct _DHCP6_INSTANCE  DHCP6_INSTANCE;
+ #define DHCP6_SERVICE_SIGNATURE   SIGNATURE_32 ('D', 'H', '6', 'S')\r
+ #define DHCP6_INSTANCE_SIGNATURE  SIGNATURE_32 ('D', 'H', '6', 'I')\r
\r
++//\r
++// For more information on DHCP options see RFC 8415, Section 21.1\r
++// \r
++// The format of DHCP options is:\r
++//\r
++//     0                   1                   2                   3\r
++//     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\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |          option-code          |           option-len          |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |                          option-data                          |\r
++//    |                      (option-len octets)                      |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//\r
++#define DHCP6_SIZE_OF_OPT_CODE    (sizeof(UINT16))\r
++#define DHCP6_SIZE_OF_OPT_LEN     (sizeof(UINT16))\r
++\r
++// Combined size of Code and Length\r
++#define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN  (DHCP6_SIZE_OF_OPT_CODE + \\r
++                                              DHCP6_SIZE_OF_OPT_LEN)\r
++\r
++STATIC_ASSERT (\r
++               DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4,\r
++               "Combined size of Code and Length must be 4 per RFC 8415"\r
++               );\r
++\r
++// Offset to the length is just past the code\r
++#define DHCP6_OPT_LEN_OFFSET(a)  (a + DHCP6_SIZE_OF_OPT_CODE)\r
++STATIC_ASSERT (\r
++               DHCP6_OPT_LEN_OFFSET (0) == 2,\r
++               "Offset of length is + 2 past start of option"\r
++               );\r
++\r
++#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)\r
++STATIC_ASSERT (\r
++               DHCP6_OPT_DATA_OFFSET(0) == 4,\r
++               "Offset to option data should be +4 from start of option"\r
++               );\r
++\r
+ #define DHCP6_PACKET_ALL        0\r
+ #define DHCP6_PACKET_STATEFUL   1\r
+ #define DHCP6_PACKET_STATELESS  2\r
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+index dcd01e6268..1401910950 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+@@ -3,9 +3,9 @@
\r
+   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
++  Copyright (c) Microsoft Corporation\r
\r
+   SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-\r
+ **/\r
\r
+ #include "Dhcp6Impl.h"\r
+@@ -930,7 +930,8 @@ Dhcp6SendSolicitMsg   (
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE + UserLen;\r
+@@ -944,54 +945,64 @@ Dhcp6SendSolicitMsg   (
+   Cursor = Packet->Dhcp6.Option;\r
\r
+   Length = HTONS (ClientId->Length);\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptClientId),\r
+              Length,\r
+              ClientId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendIaOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendIaOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance->IaCb.Ia,\r
+              Instance->IaCb.T1,\r
+              Instance->IaCb.T2,\r
+              Packet->Dhcp6.Header.MessageType\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+   //\r
+   // Append user-defined when configurate Dhcp6 service.\r
+   //\r
+   for (Index = 0; Index < Instance->Config->OptionCount; Index++) {\r
+     UserOpt = Instance->Config->OptionList[Index];\r
+-    Cursor  = Dhcp6AppendOption (\r
+-                Cursor,\r
++    Status  = Dhcp6AppendOption (\r
++                Packet,\r
++                &Cursor,\r
+                 UserOpt->OpCode,\r
+                 UserOpt->OpLen,\r
+                 UserOpt->Data\r
+                 );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+-  //\r
+-  // Determine the size/length of packet.\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+   // Callback to user with the packet to be sent and check the user's feedback.\r
+   //\r
+   Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -1005,10 +1016,8 @@ Dhcp6SendSolicitMsg   (
+   Instance->StartTime = 0;\r
\r
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -1020,6 +1029,14 @@ Dhcp6SendSolicitMsg   (
+            Elapsed,\r
+            Instance->Config->SolicitRetransmission\r
+            );\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool (Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+@@ -1110,7 +1127,8 @@ Dhcp6SendRequestMsg (
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE + UserLen;\r
+@@ -1124,51 +1142,67 @@ Dhcp6SendRequestMsg (
+   Cursor = Packet->Dhcp6.Option;\r
\r
+   Length = HTONS (ClientId->Length);\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptClientId),\r
+              Length,\r
+              ClientId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptServerId),\r
+              ServerId->Length,\r
+              ServerId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendIaOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendIaOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance->IaCb.Ia,\r
+              Instance->IaCb.T1,\r
+              Instance->IaCb.T2,\r
+              Packet->Dhcp6.Header.MessageType\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+   //\r
+   // Append user-defined when configurate Dhcp6 service.\r
+   //\r
+   for (Index = 0; Index < Instance->Config->OptionCount; Index++) {\r
+     UserOpt = Instance->Config->OptionList[Index];\r
+-    Cursor  = Dhcp6AppendOption (\r
+-                Cursor,\r
++    Status  = Dhcp6AppendOption (\r
++                Packet,\r
++                &Cursor,\r
+                 UserOpt->OpCode,\r
+                 UserOpt->OpLen,\r
+                 UserOpt->Data\r
+                 );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+-  //\r
+-  // Determine the size/length of packet.\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+@@ -1177,8 +1211,7 @@ Dhcp6SendRequestMsg (
+   Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet);\r
\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -1194,14 +1227,21 @@ Dhcp6SendRequestMsg (
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+   // Enqueue the sent packet for the retransmission in case reply timeout.\r
+   //\r
+   return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool (Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+@@ -1266,7 +1306,8 @@ Dhcp6SendDeclineMsg (
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE;\r
+@@ -1280,42 +1321,58 @@ Dhcp6SendDeclineMsg (
+   Cursor = Packet->Dhcp6.Option;\r
\r
+   Length = HTONS (ClientId->Length);\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptClientId),\r
+              Length,\r
+              ClientId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptServerId),\r
+              ServerId->Length,\r
+              ServerId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType);\r
++  Status = Dhcp6AppendIaOption (\r
++             Packet,\r
++             &Cursor,\r
++             DecIa,\r
++             0,\r
++             0,\r
++             Packet->Dhcp6.Header.MessageType\r
++             );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  //\r
+-  // Determine the size/length of packet.\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+   // Callback to user with the packet to be sent and check the user's feedback.\r
+   //\r
+   Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -1329,16 +1386,22 @@ Dhcp6SendDeclineMsg (
+   Instance->StartTime = 0;\r
\r
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+   // Enqueue the sent packet for the retransmission in case reply timeout.\r
+   //\r
+   return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool (Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+@@ -1399,7 +1462,8 @@ Dhcp6SendReleaseMsg (
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE;\r
+@@ -1413,45 +1477,61 @@ Dhcp6SendReleaseMsg (
+   Cursor = Packet->Dhcp6.Option;\r
\r
+   Length = HTONS (ClientId->Length);\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptClientId),\r
+              Length,\r
+              ClientId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+   //\r
+   // ServerId is extracted from packet, it's network order.\r
+   //\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptServerId),\r
+              ServerId->Length,\r
+              ServerId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType);\r
++  Status = Dhcp6AppendIaOption (\r
++             Packet,\r
++             &Cursor,\r
++             RelIa,\r
++             0,\r
++             0,\r
++             Packet->Dhcp6.Header.MessageType\r
++             );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  //\r
+-  // Determine the size/length of packet\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+   // Callback to user with the packet to be sent and check the user's feedback.\r
+   //\r
+   Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -1461,16 +1541,22 @@ Dhcp6SendReleaseMsg (
+   Instance->IaCb.Ia->State = Dhcp6Releasing;\r
\r
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+   // Enqueue the sent packet for the retransmission in case reply timeout.\r
+   //\r
+   return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool (Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+@@ -1524,12 +1610,14 @@ Dhcp6SendRenewRebindMsg (
+     UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);\r
+   }\r
\r
++\r
+   //\r
+   // Create the Dhcp6 packet and initialize common fields.\r
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE + UserLen;\r
+@@ -1543,26 +1631,38 @@ Dhcp6SendRenewRebindMsg (
+   Cursor = Packet->Dhcp6.Option;\r
\r
+   Length = HTONS (ClientId->Length);\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptClientId),\r
+              Length,\r
+              ClientId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendIaOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendIaOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance->IaCb.Ia,\r
+              Instance->IaCb.T1,\r
+              Instance->IaCb.T2,\r
+              Packet->Dhcp6.Header.MessageType\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+   if (!RebindRequest) {\r
+     //\r
+@@ -1578,18 +1678,22 @@ Dhcp6SendRenewRebindMsg (
+                Dhcp6OptServerId\r
+                );\r
+     if (Option == NULL) {\r
+-      FreePool (Packet);\r
+-      return EFI_DEVICE_ERROR;\r
++      Status = EFI_DEVICE_ERROR;\r
++      goto ON_ERROR;\r
+     }\r
\r
+     ServerId = (EFI_DHCP6_DUID *)(Option + 2);\r
\r
+-    Cursor = Dhcp6AppendOption (\r
+-               Cursor,\r
++    Status = Dhcp6AppendOption (\r
++               Packet,\r
++               &Cursor,\r
+                HTONS (Dhcp6OptServerId),\r
+                ServerId->Length,\r
+                ServerId->Duid\r
+                );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+   //\r
+@@ -1597,18 +1701,19 @@ Dhcp6SendRenewRebindMsg (
+   //\r
+   for (Index = 0; Index < Instance->Config->OptionCount; Index++) {\r
+     UserOpt = Instance->Config->OptionList[Index];\r
+-    Cursor  = Dhcp6AppendOption (\r
+-                Cursor,\r
++    Status  = Dhcp6AppendOption (\r
++                Packet,\r
++                &Cursor,\r
+                 UserOpt->OpCode,\r
+                 UserOpt->OpLen,\r
+                 UserOpt->Data\r
+                 );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+-  //\r
+-  // Determine the size/length of packet.\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
++\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+@@ -1618,10 +1723,8 @@ Dhcp6SendRenewRebindMsg (
+   Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing;\r
\r
+   Status = Dhcp6CallbackUser (Instance, Event, &Packet);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -1638,16 +1741,22 @@ Dhcp6SendRenewRebindMsg (
+   Instance->StartTime = 0;\r
\r
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+   // Enqueue the sent packet for the retransmission in case reply timeout.\r
+   //\r
+   return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool (Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+@@ -1811,7 +1920,8 @@ Dhcp6SendInfoRequestMsg (
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE + UserLen;\r
+@@ -1828,44 +1938,56 @@ Dhcp6SendInfoRequestMsg (
\r
+   if (SendClientId) {\r
+     Length = HTONS (ClientId->Length);\r
+-    Cursor = Dhcp6AppendOption (\r
+-               Cursor,\r
++    Status = Dhcp6AppendOption (\r
++               Packet,\r
++               &Cursor,\r
+                HTONS (Dhcp6OptClientId),\r
+                Length,\r
+                ClientId->Duid\r
+                );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              OptionRequest->OpCode,\r
+              OptionRequest->OpLen,\r
+              OptionRequest->Data\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+   //\r
+   // Append user-defined when configurate Dhcp6 service.\r
+   //\r
+   for (Index = 0; Index < OptionCount; Index++) {\r
+     UserOpt = OptionList[Index];\r
+-    Cursor  = Dhcp6AppendOption (\r
+-                Cursor,\r
++    Status  = Dhcp6AppendOption (\r
++                Packet,\r
++                &Cursor,\r
+                 UserOpt->OpCode,\r
+                 UserOpt->OpLen,\r
+                 UserOpt->Data\r
+                 );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+-  //\r
+-  // Determine the size/length of packet.\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+@@ -1877,16 +1999,22 @@ Dhcp6SendInfoRequestMsg (
+   // Send info-request packet with no state.\r
+   //\r
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+   // Enqueue the sent packet for the retransmission in case reply timeout.\r
+   //\r
+   return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission);\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool (Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+@@ -1937,7 +2065,8 @@ Dhcp6SendConfirmMsg (
+   //\r
+   Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);\r
+   if (Packet == NULL) {\r
+-    return EFI_OUT_OF_RESOURCES;\r
++    Status = EFI_OUT_OF_RESOURCES;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   Packet->Size                       = DHCP6_BASE_PACKET_SIZE + UserLen;\r
+@@ -1951,54 +2080,64 @@ Dhcp6SendConfirmMsg (
+   Cursor = Packet->Dhcp6.Option;\r
\r
+   Length = HTONS (ClientId->Length);\r
+-  Cursor = Dhcp6AppendOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendOption (\r
++             Packet,\r
++             &Cursor,\r
+              HTONS (Dhcp6OptClientId),\r
+              Length,\r
+              ClientId->Duid\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendETOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendETOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance,\r
+              &Elapsed\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+-  Cursor = Dhcp6AppendIaOption (\r
+-             Cursor,\r
++  Status = Dhcp6AppendIaOption (\r
++             Packet,\r
++             &Cursor,\r
+              Instance->IaCb.Ia,\r
+              Instance->IaCb.T1,\r
+              Instance->IaCb.T2,\r
+              Packet->Dhcp6.Header.MessageType\r
+              );\r
++  if (EFI_ERROR (Status)) {\r
++    goto ON_ERROR;\r
++  }\r
\r
+   //\r
+   // Append user-defined when configurate Dhcp6 service.\r
+   //\r
+   for (Index = 0; Index < Instance->Config->OptionCount; Index++) {\r
+     UserOpt = Instance->Config->OptionList[Index];\r
+-    Cursor  = Dhcp6AppendOption (\r
+-                Cursor,\r
++    Status  = Dhcp6AppendOption (\r
++                Packet,\r
++                &Cursor,\r
+                 UserOpt->OpCode,\r
+                 UserOpt->OpLen,\r
+                 UserOpt->Data\r
+                 );\r
++    if (EFI_ERROR (Status)) {\r
++      goto ON_ERROR;\r
++    }\r
+   }\r
\r
+-  //\r
+-  // Determine the size/length of packet.\r
+-  //\r
+-  Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);\r
+   ASSERT (Packet->Size > Packet->Length + 8);\r
\r
+   //\r
+   // Callback to user with the packet to be sent and check the user's feedback.\r
+   //\r
+   Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+@@ -2012,16 +2151,22 @@ Dhcp6SendConfirmMsg (
+   Instance->StartTime = 0;\r
\r
+   Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);\r
+-\r
+   if (EFI_ERROR (Status)) {\r
+-    FreePool (Packet);\r
+-    return Status;\r
++    goto ON_ERROR;\r
+   }\r
\r
+   //\r
+   // Enqueue the sent packet for the retransmission in case reply timeout.\r
+   //\r
+   return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);\r
++\r
++ON_ERROR:\r
++\r
++  if (Packet) {\r
++    FreePool(Packet);\r
++  }\r
++\r
++  return Status;\r
+ }\r
\r
+ /**\r
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
+index e6368b5b1c..8f4bd1eb0f 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
+@@ -142,12 +142,12 @@ Dhcp6GenerateClientId (
+   }\r
\r
+   Status = gRT->SetVariable (\r
+-                  L"ClientId",\r
+-                  &gEfiDhcp6ServiceBindingProtocolGuid,\r
+-                  (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),\r
+-                  Duid->Length + 2,\r
+-                  (VOID *)Duid\r
+-                  );\r
++                             L"ClientId",\r
++                             &gEfiDhcp6ServiceBindingProtocolGuid,\r
++                             (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),\r
++                             Duid->Length + 2,\r
++                             (VOID *)Duid\r
++                             );\r
+   if (EFI_ERROR (Status)) {\r
+     FreePool (Duid);\r
+     return NULL;\r
+@@ -192,10 +192,10 @@ Dhcp6CopyConfigData (
+     }\r
\r
+     CopyMem (\r
+-      DstCfg->SolicitRetransmission,\r
+-      SorCfg->SolicitRetransmission,\r
+-      sizeof (EFI_DHCP6_RETRANSMISSION)\r
+-      );\r
++             DstCfg->SolicitRetransmission,\r
++             SorCfg->SolicitRetransmission,\r
++             sizeof (EFI_DHCP6_RETRANSMISSION)\r
++             );\r
+   }\r
\r
+   if ((SorCfg->OptionList != NULL) && (SorCfg->OptionCount != 0)) {\r
+@@ -221,10 +221,10 @@ Dhcp6CopyConfigData (
+       }\r
\r
+       CopyMem (\r
+-        DstCfg->OptionList[Index],\r
+-        SorCfg->OptionList[Index],\r
+-        OptionSize\r
+-        );\r
++               DstCfg->OptionList[Index],\r
++               SorCfg->OptionList[Index],\r
++               OptionSize\r
++               );\r
+     }\r
+   }\r
\r
+@@ -422,10 +422,10 @@ Dhcp6CheckAddress (
\r
+     for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {\r
+       if (CompareMem (\r
+-            &Addresses[Index1],\r
+-            &Ia->IaAddress[Index2],\r
+-            sizeof (EFI_IPv6_ADDRESS)\r
+-            ) == 0)\r
++                      &Addresses[Index1],\r
++                      &Ia->IaAddress[Index2],\r
++                      sizeof (EFI_IPv6_ADDRESS)\r
++                      ) == 0)\r
+       {\r
+         Found = TRUE;\r
+         break;\r
+@@ -503,28 +503,28 @@ Dhcp6DepriveAddress (
\r
+     for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {\r
+       if (CompareMem (\r
+-            &Addresses[Index1],\r
+-            &Ia->IaAddress[Index2],\r
+-            sizeof (EFI_IPv6_ADDRESS)\r
+-            ) == 0)\r
++                      &Addresses[Index1],\r
++                      &Ia->IaAddress[Index2],\r
++                      sizeof (EFI_IPv6_ADDRESS)\r
++                      ) == 0)\r
+       {\r
+         //\r
+         // Copy the deprived address to the copy of Ia\r
+         //\r
+         CopyMem (\r
+-          &IaCopy->IaAddress[Index1],\r
+-          &Ia->IaAddress[Index2],\r
+-          sizeof (EFI_DHCP6_IA_ADDRESS)\r
+-          );\r
++                 &IaCopy->IaAddress[Index1],\r
++                 &Ia->IaAddress[Index2],\r
++                 sizeof (EFI_DHCP6_IA_ADDRESS)\r
++                 );\r
+         //\r
+         // Delete the deprived address from the instance Ia\r
+         //\r
+         if (Index2 + 1 < Ia->IaAddressCount) {\r
+           CopyMem (\r
+-            &Ia->IaAddress[Index2],\r
+-            &Ia->IaAddress[Index2 + 1],\r
+-            (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)\r
+-            );\r
++                   &Ia->IaAddress[Index2],\r
++                   &Ia->IaAddress[Index2 + 1],\r
++                   (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)\r
++                   );\r
+         }\r
\r
+         Found = TRUE;\r
+@@ -577,24 +577,33 @@ Dhcp6OnTransmitted (
+ }\r
\r
+ /**\r
+-  Append the option to Buf, and move Buf to the end.\r
++  Append the option to Buf, update the length of packet, and move Buf to the end.\r
\r
+-  @param[in, out] Buf           The pointer to the buffer.\r
+-  @param[in]      OptType       The option type.\r
+-  @param[in]      OptLen        The length of option contents.\r
+-  @param[in]      Data          The pointer to the option content.\r
++  @param[in, out] Packet         A pointer to the packet, on success Packet->Length\r
++                                 will be updated.\r
++  @param[in, out] PacketCursor   The pointer in the packet, on success PacketCursor\r
++                                 will be moved to the end of the option.\r
++  @param[in]      OptType        The option type.\r
++  @param[in]      OptLen         The length of option contents.\r
++  @param[in]      Data           The pointer to the option content.\r
\r
+-  @return         Buf           The position to append the next option.\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendOption (\r
+-  IN OUT UINT8   *Buf,\r
+-  IN     UINT16  OptType,\r
+-  IN     UINT16  OptLen,\r
+-  IN     UINT8   *Data\r
++  IN OUT EFI_DHCP6_PACKET  *Packet,\r
++  IN OUT UINT8             **PacketCursor,\r
++  IN     UINT16            OptType,\r
++  IN     UINT16            OptLen,\r
++  IN     UINT8             *Data\r
+   )\r
+ {\r
++  UINT32  Length;\r
++  UINT32  BytesNeeded;\r
++\r
+   //\r
+   //  The format of Dhcp6 option:\r
+   //\r
+@@ -607,35 +616,95 @@ Dhcp6AppendOption (
+   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+   //\r
\r
+-  ASSERT (OptLen != 0);\r
++  //\r
++  // Verify the arguments are valid\r
++  //\r
++  if (Packet == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (Data == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (OptLen == 0) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Verify the PacketCursor is within the packet\r
++  //\r
++  if (  (*PacketCursor < Packet->Dhcp6.Option)\r
++     || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))\r
++  {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Calculate the bytes needed for the option\r
++  //\r
++  BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS(OptLen);\r
\r
+-  WriteUnaligned16 ((UINT16 *)Buf, OptType);\r
+-  Buf += 2;\r
+-  WriteUnaligned16 ((UINT16 *)Buf, OptLen);\r
+-  Buf += 2;\r
+-  CopyMem (Buf, Data, NTOHS (OptLen));\r
+-  Buf += NTOHS (OptLen);\r
++  //\r
++  // Space remaining in the packet\r
++  //\r
++  Length = Packet->Size - Packet->Length;\r
++  if (Length < BytesNeeded) {\r
++    return EFI_BUFFER_TOO_SMALL;\r
++  }\r
++\r
++  //\r
++  // Verify the PacketCursor is within the packet\r
++  //\r
++  if (  (*PacketCursor < Packet->Dhcp6.Option)\r
++     || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))\r
++  {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
\r
+-  return Buf;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType);\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen);\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;\r
++  CopyMem (*PacketCursor, Data, NTOHS (OptLen));\r
++  *PacketCursor += NTOHS (OptLen);\r
++\r
++  // Update the packet length by the length of the option + 4 bytes\r
++  Packet->Length += BytesNeeded;\r
++\r
++  return EFI_SUCCESS;\r
+ }\r
\r
+ /**\r
+   Append the appointed IA Address option to Buf, and move Buf to the end.\r
\r
+-  @param[in, out] Buf           The pointer to the position to append.\r
++  @param[in, out] Packet        A pointer to the packet, on success Packet->Length\r
++                                will be updated.\r
++  @param[in, out] PacketCursor  The pointer in the packet, on success PacketCursor\r
++                                will be moved to the end of the option.\r
+   @param[in]      IaAddr        The pointer to the IA Address.\r
+   @param[in]      MessageType   Message type of DHCP6 package.\r
\r
+-  @return         Buf           The position to append the next option.\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendIaAddrOption (\r
+-  IN OUT UINT8                 *Buf,\r
++  IN OUT EFI_DHCP6_PACKET      *Packet,\r
++  IN OUT UINT8                 **PacketCursor,\r
+   IN     EFI_DHCP6_IA_ADDRESS  *IaAddr,\r
+   IN     UINT32                MessageType\r
+   )\r
+ {\r
++  UINT32  BytesNeeded;\r
++  UINT32  Length;\r
++\r
+   //  The format of the IA Address option is:\r
+   //\r
+   //       0                   1                   2                   3\r
+@@ -657,17 +726,60 @@ Dhcp6AppendIaAddrOption (
+   //      .                                                               .\r
+   //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
\r
++  //\r
++  // Verify the arguments are valid\r
++  //\r
++  if (Packet == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (IaAddr == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Verify the PacketCursor is within the packet\r
++  //\r
++  if (  (*PacketCursor < Packet->Dhcp6.Option)\r
++     || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))\r
++  {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  BytesNeeded  = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;\r
++  BytesNeeded += sizeof (EFI_IPv6_ADDRESS);\r
++  //\r
++  // Even if the preferred-lifetime is 0, it still needs to store it.\r
++  //\r
++  BytesNeeded += sizeof (IaAddr->PreferredLifetime);\r
++  //\r
++  // Even if the valid-lifetime is 0, it still needs to store it.\r
++  //\r
++  BytesNeeded += sizeof (IaAddr->ValidLifetime);\r
++\r
++  //\r
++  // Space remaining in the packet\r
++  //\r
++  Length = Packet->Size - Packet->Length;\r
++  if (Length < BytesNeeded) {\r
++    return EFI_BUFFER_TOO_SMALL;\r
++  }\r
++\r
+   //\r
+   // Fill the value of Ia Address option type\r
+   //\r
+-  WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));\r
+-  Buf += 2;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr));\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;\r
\r
+-  WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));\r
+-  Buf += 2;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;\r
\r
+-  CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
+-  Buf += sizeof (EFI_IPv6_ADDRESS);\r
++  CopyMem (*PacketCursor, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
++  *PacketCursor += sizeof (EFI_IPv6_ADDRESS);\r
\r
+   //\r
+   // Fill the value of preferred-lifetime and valid-lifetime.\r
+@@ -675,44 +787,58 @@ Dhcp6AppendIaAddrOption (
+   // should set to 0 when initiate a Confirm message.\r
+   //\r
+   if (MessageType != Dhcp6MsgConfirm) {\r
+-    WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));\r
++    WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime));\r
+   }\r
\r
+-  Buf += 4;\r
++  *PacketCursor += sizeof (IaAddr->PreferredLifetime);\r
\r
+   if (MessageType != Dhcp6MsgConfirm) {\r
+-    WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));\r
++    WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime));\r
+   }\r
\r
+-  Buf += 4;\r
++  *PacketCursor += sizeof (IaAddr->ValidLifetime);\r
++\r
++  //\r
++  // Update the packet length\r
++  //\r
++  Packet->Length += BytesNeeded;\r
\r
+-  return Buf;\r
++  return EFI_SUCCESS;\r
+ }\r
\r
+ /**\r
+   Append the appointed Ia option to Buf, and move Buf to the end.\r
\r
+-  @param[in, out] Buf           The pointer to the position to append.\r
++  @param[in, out] Packet        A pointer to the packet, on success Packet->Length\r
++                                will be updated.\r
++  @param[in, out] PacketCursor  The pointer in the packet, on success PacketCursor\r
++                                will be moved to the end of the option.\r
+   @param[in]      Ia            The pointer to the Ia.\r
+   @param[in]      T1            The time of T1.\r
+   @param[in]      T2            The time of T2.\r
+   @param[in]      MessageType   Message type of DHCP6 package.\r
\r
+-  @return         Buf           The position to append the next Ia option.\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendIaOption (\r
+-  IN OUT UINT8         *Buf,\r
+-  IN     EFI_DHCP6_IA  *Ia,\r
+-  IN     UINT32        T1,\r
+-  IN     UINT32        T2,\r
+-  IN     UINT32        MessageType\r
++  IN OUT EFI_DHCP6_PACKET  *Packet,\r
++  IN OUT UINT8             **PacketCursor,\r
++  IN     EFI_DHCP6_IA      *Ia,\r
++  IN     UINT32            T1,\r
++  IN     UINT32            T2,\r
++  IN     UINT32            MessageType\r
+   )\r
+ {\r
+-  UINT8   *AddrOpt;\r
+-  UINT16  *Len;\r
+-  UINTN   Index;\r
++  UINT8       *AddrOpt;\r
++  UINT16      *Len;\r
++  UINTN       Index;\r
++  UINT32      BytesNeeded;\r
++  UINT32      Length;\r
++  EFI_STATUS  Status;\r
\r
+   //\r
+   //  The format of IA_NA and IA_TA option:\r
+@@ -733,32 +859,74 @@ Dhcp6AppendIaOption (
+   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+   //\r
\r
++  //\r
++  // Verify the arguments are valid\r
++  //\r
++  if (Packet == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (Ia == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Verify the PacketCursor is within the packet\r
++  //\r
++  if (  (*PacketCursor < Packet->Dhcp6.Option)\r
++     || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))\r
++  {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  BytesNeeded  = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;\r
++  BytesNeeded += sizeof (Ia->Descriptor.IaId);\r
++  //\r
++  // + N for the IA_NA-options/IA_TA-options\r
++  // Dhcp6AppendIaAddrOption will need to check the length for each address\r
++  //\r
++  if (Ia->Descriptor.Type == Dhcp6OptIana) {\r
++    BytesNeeded += sizeof (T1) + sizeof (T2);\r
++  }\r
++\r
++  //\r
++  // Space remaining in the packet\r
++  //\r
++  Length = (UINT16)(Packet->Size - Packet->Length);\r
++  if (Length < BytesNeeded) {\r
++    return EFI_BUFFER_TOO_SMALL;\r
++  }\r
++\r
+   //\r
+   // Fill the value of Ia option type\r
+   //\r
+-  WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));\r
+-  Buf += 2;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type));\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;\r
\r
+   //\r
+   // Fill the len of Ia option later, keep the pointer first\r
+   //\r
+-  Len  = (UINT16 *)Buf;\r
+-  Buf += 2;\r
++  Len            = (UINT16 *)*PacketCursor;\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;\r
\r
+   //\r
+   // Fill the value of iaid\r
+   //\r
+-  WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));\r
+-  Buf += 4;\r
++  WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId));\r
++  *PacketCursor += sizeof (Ia->Descriptor.IaId);\r
\r
+   //\r
+   // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.\r
+   //\r
+   if (Ia->Descriptor.Type == Dhcp6OptIana) {\r
+-    WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));\r
+-    Buf += 4;\r
+-    WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));\r
+-    Buf += 4;\r
++    WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T1 != 0) ? T1 : 0xffffffff));\r
++    *PacketCursor += sizeof (T1);\r
++    WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T2 != 0) ? T2 : 0xffffffff));\r
++    *PacketCursor += sizeof (T2);\r
+   }\r
\r
+   //\r
+@@ -766,35 +934,51 @@ Dhcp6AppendIaOption (
+   //\r
+   for (Index = 0; Index < Ia->IaAddressCount; Index++) {\r
+     AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);\r
+-    Buf     = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);\r
++    Status  = Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);\r
++    if (EFI_ERROR (Status)) {\r
++      return Status;\r
++    }\r
+   }\r
\r
+   //\r
+   // Fill the value of Ia option length\r
+   //\r
+-  *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));\r
++  *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));\r
\r
+-  return Buf;\r
++  //\r
++  // Update the packet length\r
++  //\r
++  Packet->Length += BytesNeeded;\r
++\r
++  return EFI_SUCCESS;\r
+ }\r
\r
+ /**\r
+   Append the appointed Elapsed time option to Buf, and move Buf to the end.\r
\r
+-  @param[in, out] Buf           The pointer to the position to append.\r
++  @param[in, out] Packet        A pointer to the packet, on success Packet->Length\r
++  @param[in, out] PacketCursor  The pointer in the packet, on success PacketCursor\r
++                                will be moved to the end of the option.\r
+   @param[in]      Instance      The pointer to the Dhcp6 instance.\r
+   @param[out]     Elapsed       The pointer to the elapsed time value in\r
+-                                  the generated packet.\r
++                                the generated packet.\r
\r
+-  @return         Buf           The position to append the next Ia option.\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendETOption (\r
+-  IN OUT UINT8           *Buf,\r
+-  IN     DHCP6_INSTANCE  *Instance,\r
+-  OUT    UINT16          **Elapsed\r
++  IN OUT EFI_DHCP6_PACKET  *Packet,\r
++  IN OUT UINT8             **PacketCursor,\r
++  IN     DHCP6_INSTANCE    *Instance,\r
++  OUT    UINT16            **Elapsed\r
+   )\r
+ {\r
++  UINT32  BytesNeeded;\r
++  UINT32  Length;\r
++\r
+   //\r
+   //  The format of elapsed time option:\r
+   //\r
+@@ -806,27 +990,70 @@ Dhcp6AppendETOption (
+   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+   //\r
\r
++  //\r
++  // Verify the arguments are valid\r
++  //\r
++  if (Packet == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if (Instance == NULL) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  if ((Elapsed == NULL)) {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  //\r
++  // Verify the PacketCursor is within the packet\r
++  //\r
++  if (  (*PacketCursor < Packet->Dhcp6.Option)\r
++     || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))\r
++  {\r
++    return EFI_INVALID_PARAMETER;\r
++  }\r
++\r
++  BytesNeeded  = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;\r
++  //\r
++  // + 2 for elapsed-time\r
++  //\r
++  BytesNeeded += sizeof (UINT16);\r
++  //\r
++  // Space remaining in the packet\r
++  //\r
++  Length = Packet->Size - Packet->Length;\r
++  if (Length < BytesNeeded) {\r
++    return EFI_BUFFER_TOO_SMALL;\r
++  }\r
++\r
+   //\r
+   // Fill the value of elapsed-time option type.\r
+   //\r
+-  WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));\r
+-  Buf += 2;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime));\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;\r
\r
+   //\r
+   // Fill the len of elapsed-time option, which is fixed.\r
+   //\r
+-  WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));\r
+-  Buf += 2;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2));\r
++  *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;\r
\r
+   //\r
+   // Fill in elapsed time value with 0 value for now.  The actual value is\r
+   // filled in later just before the packet is transmitted.\r
+   //\r
+-  WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));\r
+-  *Elapsed = (UINT16 *)Buf;\r
+-  Buf     += 2;\r
++  WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0));\r
++  *Elapsed       = (UINT16 *)*PacketCursor;\r
++  *PacketCursor += sizeof (UINT16);\r
++\r
++  Packet->Length += BytesNeeded;\r
\r
+-  return Buf;\r
++  return EFI_SUCCESS;\r
+ }\r
\r
+ /**\r
+@@ -852,13 +1079,13 @@ SetElapsedTime (
+   //\r
+   gRT->GetTime (&Time, NULL);\r
+   CurrentStamp = MultU64x32 (\r
+-                   ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,\r
+-                   100\r
+-                   ) +\r
++                             ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,\r
++                             100\r
++                             ) +\r
+                  DivU64x32 (\r
+-                   Time.Nanosecond,\r
+-                   10000000\r
+-                   );\r
++                            Time.Nanosecond,\r
++                            10000000\r
++                            );\r
\r
+   //\r
+   // Sentinel value of 0 means that this is the first DHCP packet that we are\r
+@@ -1290,11 +1517,11 @@ Dhcp6GetMappingTimeOut (
\r
+   DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
+   Status   = Ip6Cfg->GetData (\r
+-                       Ip6Cfg,\r
+-                       Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+-                       &DataSize,\r
+-                       &DadXmits\r
+-                       );\r
++                              Ip6Cfg,\r
++                              Ip6ConfigDataTypeDupAddrDetectTransmits,\r
++                              &DataSize,\r
++                              &DadXmits\r
++                              );\r
+   if (EFI_ERROR (Status)) {\r
+     return Status;\r
+   }\r
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
+index 046454ff4a..06947f6c1f 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
+@@ -160,69 +160,85 @@ Dhcp6OnTransmitted (
+   );\r
\r
+ /**\r
+-  Append the appointed option to the buf, and move the buf to the end.\r
+-\r
+-  @param[in, out] Buf           The pointer to buffer.\r
+-  @param[in]      OptType       The option type.\r
+-  @param[in]      OptLen        The length of option content.s\r
+-  @param[in]      Data          The pointer to the option content.\r
+-\r
+-  @return         Buf           The position to append the next option.\r
+-\r
++  Append the option to Buf, update the length of packet, and move Buf to the end.\r
++\r
++  @param[in, out] Packet         A pointer to the packet, on success Packet->Length\r
++                                 will be updated.\r
++  @param[in, out] PacketCursor   The pointer in the packet, on success PacketCursor\r
++                                 will be moved to the end of the option.\r
++  @param[in]      OptType        The option type.\r
++  @param[in]      OptLen         The length of option contents.\r
++  @param[in]      Data           The pointer to the option content.\r
++\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendOption (\r
+-  IN OUT UINT8   *Buf,\r
+-  IN     UINT16  OptType,\r
+-  IN     UINT16  OptLen,\r
+-  IN     UINT8   *Data\r
++  IN OUT EFI_DHCP6_PACKET  *Packet,\r
++  IN OUT UINT8             **PacketCursor,\r
++  IN     UINT16            OptType,\r
++  IN     UINT16            OptLen,\r
++  IN     UINT8             *Data\r
+   );\r
\r
+ /**\r
+-  Append the Ia option to Buf, and move Buf to the end.\r
+-\r
+-  @param[in, out] Buf           The pointer to the position to append.\r
++  Append the appointed Ia option to Buf, update the Ia option length, and move Buf\r
++  to the end of the option.\r
++  @param[in, out] Packet        A pointer to the packet, on success Packet->Length\r
++                                will be updated.\r
++  @param[in, out] PacketCursor   The pointer in the packet, on success PacketCursor\r
++                                 will be moved to the end of the option.\r
+   @param[in]      Ia            The pointer to the Ia.\r
+   @param[in]      T1            The time of T1.\r
+   @param[in]      T2            The time of T2.\r
+   @param[in]      MessageType   Message type of DHCP6 package.\r
\r
+-  @return         Buf           The position to append the next Ia option.\r
+-\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendIaOption (\r
+-  IN OUT UINT8         *Buf,\r
+-  IN     EFI_DHCP6_IA  *Ia,\r
+-  IN     UINT32        T1,\r
+-  IN     UINT32        T2,\r
+-  IN     UINT32        MessageType\r
++  IN OUT EFI_DHCP6_PACKET  *Packet,\r
++  IN OUT UINT8             **PacketCursor,\r
++  IN     EFI_DHCP6_IA      *Ia,\r
++  IN     UINT32            T1,\r
++  IN     UINT32            T2,\r
++  IN     UINT32            MessageType\r
+   );\r
\r
+ /**\r
+   Append the appointed Elapsed time option to Buf, and move Buf to the end.\r
\r
+-  @param[in, out] Buf           The pointer to the position to append.\r
++  @param[in, out] Packet        A pointer to the packet, on success Packet->Length\r
++  @param[in, out] PacketCursor   The pointer in the packet, on success PacketCursor\r
++                                 will be moved to the end of the option.\r
+   @param[in]      Instance      The pointer to the Dhcp6 instance.\r
+   @param[out]     Elapsed       The pointer to the elapsed time value in\r
+                                   the generated packet.\r
\r
+-  @return         Buf           The position to append the next Ia option.\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
\r
+ **/\r
+-UINT8 *\r
++EFI_STATUS\r
+ Dhcp6AppendETOption (\r
+-  IN OUT UINT8           *Buf,\r
+-  IN     DHCP6_INSTANCE  *Instance,\r
+-  OUT    UINT16          **Elapsed\r
++  IN OUT EFI_DHCP6_PACKET  *Packet,\r
++  IN OUT UINT8             **PacketCursor,\r
++  IN     DHCP6_INSTANCE    *Instance,\r
++  OUT    UINT16            **Elapsed\r
+   );\r
\r
+ /**\r
+   Set the elapsed time based on the given instance and the pointer to the\r
+   elapsed time option.\r
\r
+-  @param[in]      Elapsed       The pointer to the position to append.\r
+-  @param[in]      Instance      The pointer to the Dhcp6 instance.\r
++  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid\r
++  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.\r
++  @retval   EFI_SUCCESS           The option is appended successfully.\r
+ **/\r
+ VOID\r
+ SetElapsedTime (\r
+-- 
+2.41.0
+
+
+From 1bd40aba86eecc8acc07547e6d14e563590b1074 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 15 Dec 2023 11:26:04 -0800
+Subject: [PATCH 02/12] SECURITY PATCH TCBZ4535 - CVE-2023-45230 - Host Based
+ Unit Test
+
+---
+ .../GoogleTest/Dhcp6DxeGoogleTest.cpp         |  27 +
+ .../GoogleTest/Dhcp6DxeGoogleTest.inf         |  44 ++
+ .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++
+ NetworkPkg/NetworkPkg.ci.yaml                 |   3 +
+ NetworkPkg/Test/NetworkPkgHostTest.dsc        | 102 ++++
+ 5 files changed, 654 insertions(+)
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+ create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc
+
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..b1fe72e195
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+@@ -0,0 +1,27 @@
++/** @file\r
++  Acts as the main entry point for the tests for the Dhcp6Dxe module.\r
++\r
++  Copyright (c) Microsoft Corporation\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <gtest/gtest.h>\r
++\r
++////////////////////////////////////////////////////////////////////////////////\r
++// Add test files here\r
++// Google Test will only pick up the tests from the files that are included\r
++// here.\r
++////////////////////////////////////////////////////////////////////////////////\r
++#include "Dhcp6IoGoogleTest.cpp"\r
++\r
++////////////////////////////////////////////////////////////////////////////////\r
++// Run the tests\r
++////////////////////////////////////////////////////////////////////////////////\r
++int\r
++main (\r
++  int   argc,\r
++  char  *argv[]\r
++  )\r
++{\r
++  testing::InitGoogleTest (&argc, argv);\r
++  return RUN_ALL_TESTS ();\r
++}\r
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+new file mode 100644
+index 0000000000..c7ec42b322
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+@@ -0,0 +1,44 @@
++## @file\r
++# Unit test suite for the Dhcp6Dxe using Google Test\r
++#\r
++# Copyright (c) Microsoft Corporation.<BR>\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++##\r
++[Defines]\r
++  INF_VERSION         = 0x00010017\r
++  BASE_NAME           = Dhcp6DxeGoogleTest\r
++  FILE_GUID           = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9\r
++  VERSION_STRING      = 1.0\r
++  MODULE_TYPE         = HOST_APPLICATION\r
++#\r
++# The following information is for reference only and not required by the build tools.\r
++#\r
++#  VALID_ARCHITECTURES           = IA32 X64 AARCH64\r
++#\r
++[Sources]\r
++  Dhcp6DxeGoogleTest.cpp\r
++  Dhcp6IoGoogleTest.cpp\r
++  ../Dhcp6Io.c\r
++  ../Dhcp6Utility.c\r
++\r
++\r
++[Packages]\r
++  MdePkg/MdePkg.dec\r
++  MdeModulePkg/MdeModulePkg.dec\r
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
++  NetworkPkg/NetworkPkg.dec\r
++\r
++[LibraryClasses]\r
++  GoogleTestLib\r
++  DebugLib\r
++  NetLib\r
++  PcdLib\r
++\r
++[Protocols]\r
++  gEfiDhcp6ServiceBindingProtocolGuid\r
++\r
++[Pcd]\r
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType\r
++\r
++[Guids]\r
++  gZeroGuid  
+\ No newline at end of file
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+new file mode 100644
+index 0000000000..dad6a42b12
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+@@ -0,0 +1,478 @@
++/** @file\r
++  Tests for Dhcp6Io.c.\r
++\r
++  Copyright (c) Microsoft Corporation\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <gtest/gtest.h>\r
++\r
++extern "C" {\r
++  #include <Uefi.h>\r
++  #include <Library/BaseLib.h>\r
++  #include <Library/DebugLib.h>\r
++  #include <Library/BaseMemoryLib.h>\r
++  #include "../Dhcp6Impl.h"\r
++  #include "../Dhcp6Utility.h"\r
++}\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++// Defines\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++#define DHCP6_PACKET_MAX_LEN  1500\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++////////////////////////////////////////////////////////////////////////\r
++// Symbol Definitions\r
++// These functions are not directly under test - but required to compile\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++// This definition is used by this test but is also required to compile\r
++// by Dhcp6Io.c\r
++EFI_IPv6_ADDRESS  mAllDhcpRelayAndServersAddress = {\r
++  { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }\r
++};\r
++\r
++EFI_STATUS\r
++EFIAPI\r
++UdpIoSendDatagram (\r
++  IN  UDP_IO           *UdpIo,\r
++  IN  NET_BUF          *Packet,\r
++  IN  UDP_END_POINT    *EndPoint OPTIONAL,\r
++  IN  EFI_IP_ADDRESS   *Gateway  OPTIONAL,\r
++  IN  UDP_IO_CALLBACK  CallBack,\r
++  IN  VOID             *Context\r
++  )\r
++{\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++EFI_STATUS\r
++EFIAPI\r
++UdpIoRecvDatagram (\r
++  IN  UDP_IO           *UdpIo,\r
++  IN  UDP_IO_CALLBACK  CallBack,\r
++  IN  VOID             *Context,\r
++  IN  UINT32           HeadLen\r
++  )\r
++{\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++// Dhcp6AppendOptionTest Tests\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++class Dhcp6AppendOptionTest : public ::testing::Test {\r
++public:\r
++  UINT8 *Buffer = NULL;\r
++  EFI_DHCP6_PACKET *Packet;\r
++\r
++protected:\r
++  // Add any setup code if needed\r
++  virtual void\r
++  SetUp (\r
++    )\r
++  {\r
++    // Initialize any resources or variables\r
++    Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
++    ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++\r
++    Packet       = (EFI_DHCP6_PACKET *)Buffer;\r
++    Packet->Size = DHCP6_PACKET_MAX_LEN;\r
++  }\r
++\r
++  // Add any cleanup code if needed\r
++  virtual void\r
++  TearDown (\r
++    )\r
++  {\r
++    // Clean up any resources or variables\r
++    if (Buffer != NULL) {\r
++      FreePool (Buffer);\r
++    }\r
++  }\r
++};\r
++\r
++// Test Description:\r
++// Attempt to append an option to a packet that is too small by a duid that is too large\r
++TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) {\r
++  UINT8           *Cursor;\r
++  EFI_DHCP6_DUID  *UntrustedDuid;\r
++  EFI_STATUS      Status;\r
++\r
++  UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));\r
++  ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);\r
++\r
++  UntrustedDuid->Length = NTOHS (0xFFFF);\r
++\r
++  Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Status = Dhcp6AppendOption (\r
++             Dhcp6AppendOptionTest::Packet,\r
++             &Cursor,\r
++             HTONS (Dhcp6OptServerId),\r
++             UntrustedDuid->Length,\r
++             UntrustedDuid->Duid\r
++             );\r
++\r
++  ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
++}\r
++\r
++// Test Description:\r
++// Attempt to append an option to a packet that is large enough\r
++TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {\r
++  UINT8           *Cursor;\r
++  EFI_DHCP6_DUID  *UntrustedDuid;\r
++  EFI_STATUS      Status;\r
++  UINTN           OriginalLength;\r
++\r
++  UINT8  Duid[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };\r
++\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++  OriginalLength = Packet->Length;\r
++\r
++  UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));\r
++  ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);\r
++\r
++  UntrustedDuid->Length = NTOHS (sizeof (Duid));\r
++  CopyMem (UntrustedDuid->Duid, Duid, sizeof (Duid));\r
++\r
++  Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Status = Dhcp6AppendOption (\r
++             Dhcp6AppendOptionTest::Packet,\r
++             &Cursor,\r
++             HTONS (Dhcp6OptServerId),\r
++             UntrustedDuid->Length,\r
++             UntrustedDuid->Duid\r
++             );\r
++\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++\r
++  // verify that the pointer to cursor moved by the expected amount\r
++  ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendOptionTest::Packet->Dhcp6.Option + sizeof (Duid) + 4);\r
++\r
++  // verify that the length of the packet is now the expected amount\r
++  ASSERT_EQ (Dhcp6AppendOptionTest::Packet->Length, OriginalLength + sizeof (Duid) + 4);\r
++}\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++// Dhcp6AppendETOption Tests\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++class Dhcp6AppendETOptionTest : public ::testing::Test {\r
++public:\r
++  UINT8 *Buffer = NULL;\r
++  EFI_DHCP6_PACKET *Packet;\r
++\r
++protected:\r
++  // Add any setup code if needed\r
++  virtual void\r
++  SetUp (\r
++    )\r
++  {\r
++    // Initialize any resources or variables\r
++    Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
++    ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++\r
++    Packet         = (EFI_DHCP6_PACKET *)Buffer;\r
++    Packet->Size   = DHCP6_PACKET_MAX_LEN;\r
++    Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++  }\r
++\r
++  // Add any cleanup code if needed\r
++  virtual void\r
++  TearDown (\r
++    )\r
++  {\r
++    // Clean up any resources or variables\r
++    if (Buffer != NULL) {\r
++      FreePool (Buffer);\r
++    }\r
++  }\r
++};\r
++\r
++// Test Description:\r
++// Attempt to append an option to a packet that is too small by a duid that is too large\r
++TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {\r
++  UINT8           *Cursor;\r
++  EFI_STATUS      Status;\r
++  DHCP6_INSTANCE  Instance;\r
++  UINT16          ElapsedTimeVal;\r
++  UINT16          *ElapsedTime;\r
++\r
++  Cursor      = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;\r
++  ElapsedTime = &ElapsedTimeVal;\r
++\r
++  Packet->Length = Packet->Size - 2;\r
++\r
++  Status = Dhcp6AppendETOption (\r
++             Dhcp6AppendETOptionTest::Packet,\r
++             &Cursor,\r
++             &Instance, // Instance is not used in this function\r
++             &ElapsedTime\r
++             );\r
++\r
++  // verify that we error out because the packet is too small for the option header\r
++  ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
++\r
++  // reset the length\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++}\r
++\r
++// Test Description:\r
++// Attempt to append an option to a packet that is large enough\r
++TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {\r
++  UINT8           *Cursor;\r
++  EFI_STATUS      Status;\r
++  DHCP6_INSTANCE  Instance;\r
++  UINT16          ElapsedTimeVal;\r
++  UINT16          *ElapsedTime;\r
++  UINTN           ExpectedSize;\r
++  UINTN           OriginalLength;\r
++\r
++  Cursor         = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;\r
++  ElapsedTime    = &ElapsedTimeVal;\r
++  ExpectedSize   = 6;\r
++  OriginalLength = Packet->Length;\r
++\r
++  Status = Dhcp6AppendETOption (\r
++             Dhcp6AppendETOptionTest::Packet,\r
++             &Cursor,\r
++             &Instance, // Instance is not used in this function\r
++             &ElapsedTime\r
++             );\r
++\r
++  // verify that the status is EFI_SUCCESS\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++\r
++  // verify that the pointer to cursor moved by the expected amount\r
++  ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendETOptionTest::Packet->Dhcp6.Option + ExpectedSize);\r
++\r
++  // verify that the length of the packet is now the expected amount\r
++  ASSERT_EQ (Dhcp6AppendETOptionTest::Packet->Length, OriginalLength + ExpectedSize);\r
++}\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++// Dhcp6AppendIaOption Tests\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++class Dhcp6AppendIaOptionTest : public ::testing::Test {\r
++public:\r
++  UINT8 *Buffer = NULL;\r
++  EFI_DHCP6_PACKET *Packet;\r
++  EFI_DHCP6_IA *Ia;\r
++\r
++protected:\r
++  // Add any setup code if needed\r
++  virtual void\r
++  SetUp (\r
++    )\r
++  {\r
++    // Initialize any resources or variables\r
++    Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
++    ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++\r
++    Packet       = (EFI_DHCP6_PACKET *)Buffer;\r
++    Packet->Size = DHCP6_PACKET_MAX_LEN;\r
++\r
++    Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);\r
++    ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);\r
++\r
++    CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));\r
++    CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));\r
++\r
++    Ia->IaAddressCount = 2;\r
++  }\r
++\r
++  // Add any cleanup code if needed\r
++  virtual void\r
++  TearDown (\r
++    )\r
++  {\r
++    // Clean up any resources or variables\r
++    if (Buffer != NULL) {\r
++      FreePool (Buffer);\r
++    }\r
++\r
++    if (Ia != NULL) {\r
++      FreePool (Ia);\r
++    }\r
++  }\r
++};\r
++\r
++// Test Description:\r
++// Attempt to append an option to a packet that doesn't have enough space\r
++// for the option header\r
++TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) {\r
++  UINT8       *Cursor;\r
++  EFI_STATUS  Status;\r
++\r
++  Packet->Length = Packet->Size - 2;\r
++\r
++  Ia->Descriptor.Type = Dhcp6OptIana;\r
++  Ia->Descriptor.IaId = 0x12345678;\r
++\r
++  Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Status = Dhcp6AppendIaOption (\r
++             Dhcp6AppendIaOptionTest::Packet,\r
++             &Cursor,\r
++             Ia,\r
++             0x12345678,\r
++             0x11111111,\r
++             Dhcp6OptIana\r
++             );\r
++\r
++  // verify that we error out because the packet is too small for the option header\r
++  ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
++\r
++  // reset the length\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++}\r
++\r
++// Test Description:\r
++// Attempt to append an option to a packet that doesn't have enough space\r
++// for the option header\r
++TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) {\r
++  UINT8       *Cursor;\r
++  EFI_STATUS  Status;\r
++\r
++  // Use up nearly all the space in the packet\r
++  Packet->Length = Packet->Size - 2;\r
++\r
++  Ia->Descriptor.Type = Dhcp6OptIata;\r
++  Ia->Descriptor.IaId = 0x12345678;\r
++\r
++  Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Status = Dhcp6AppendIaOption (\r
++             Dhcp6AppendIaOptionTest::Packet,\r
++             &Cursor,\r
++             Ia,\r
++             0,\r
++             0,\r
++             Dhcp6OptIata\r
++             );\r
++\r
++  // verify that we error out because the packet is too small for the option header\r
++  ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
++\r
++  // reset the length\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++}\r
++\r
++TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) {\r
++  UINT8       *Cursor;\r
++  EFI_STATUS  Status;\r
++  UINTN       ExpectedSize;\r
++  UINTN       OriginalLength;\r
++\r
++  //\r
++  // 2 bytes for the option header type\r
++  //\r
++  ExpectedSize = 2;\r
++  //\r
++  // 2 bytes for the option header length\r
++  //\r
++  ExpectedSize += 2;\r
++  //\r
++  // 4 bytes for the IAID\r
++  //\r
++  ExpectedSize += 4;\r
++  //\r
++  // + 4 bytes for the T1\r
++  //\r
++  ExpectedSize += 4;\r
++  //\r
++  // + 4 bytes for the T2\r
++  //\r
++  ExpectedSize += 4;\r
++  //\r
++  // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;\r
++  //   + 2 bytes for the option header type\r
++  //   + 2 bytes for the option header length\r
++  //   + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address\r
++  //\r
++  ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;\r
++\r
++  Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++  OriginalLength = Packet->Length;\r
++\r
++  Ia->Descriptor.Type = Dhcp6OptIana;\r
++  Ia->Descriptor.IaId = 0x12345678;\r
++\r
++  Status = Dhcp6AppendIaOption (\r
++             Dhcp6AppendIaOptionTest::Packet,\r
++             &Cursor,\r
++             Ia,\r
++             0x12345678,\r
++             0x12345678,\r
++             Dhcp6OptIana\r
++             );\r
++\r
++  // verify that the pointer to cursor moved by the expected amount\r
++  ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);\r
++\r
++  // verify that the length of the packet is now the expected amount\r
++  ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);\r
++\r
++  // verify that the status is EFI_SUCCESS\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++}\r
++\r
++TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {\r
++  UINT8       *Cursor;\r
++  EFI_STATUS  Status;\r
++  UINTN       ExpectedSize;\r
++  UINTN       OriginalLength;\r
++\r
++  //\r
++  // 2 bytes for the option header type\r
++  //\r
++  ExpectedSize = 2;\r
++  //\r
++  // 2 bytes for the option header length\r
++  //\r
++  ExpectedSize += 2;\r
++  //\r
++  // 4 bytes for the IAID\r
++  //\r
++  ExpectedSize += 4;\r
++  //\r
++  // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;\r
++  //   + 2 bytes for the option header type\r
++  //   + 2 bytes for the option header length\r
++  //   + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address\r
++  //\r
++  ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;\r
++\r
++  Cursor      = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++  OriginalLength = Packet->Length;\r
++\r
++  Ia->Descriptor.Type = Dhcp6OptIata;\r
++  Ia->Descriptor.IaId = 0x12345678;\r
++\r
++  Status = Dhcp6AppendIaOption (\r
++             Dhcp6AppendIaOptionTest::Packet,\r
++             &Cursor,\r
++             Ia,\r
++             0,\r
++             0,\r
++             Dhcp6OptIata\r
++             );\r
++\r
++  // verify that the pointer to cursor moved by the expected amount\r
++  ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);\r
++\r
++  // verify that the length of the packet is now the expected amount\r
++  ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);\r
++\r
++  // verify that the status is EFI_SUCCESS\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++}\r
+diff --git a/NetworkPkg/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml
+index 07dc7abd69..e82e0c6256 100644
+--- a/NetworkPkg/NetworkPkg.ci.yaml
++++ b/NetworkPkg/NetworkPkg.ci.yaml
+@@ -24,6 +24,9 @@
+     "CompilerPlugin": {\r
+         "DscPath": "NetworkPkg.dsc"\r
+     },\r
++    "HostUnitTestCompilerPlugin": {\r
++        "DscPath": "Test/NetworkPkgHostTest.dsc"\r
++    },\r
+     "CharEncodingCheck": {\r
+         "IgnoreFiles": []\r
+     },\r
+diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+new file mode 100644
+index 0000000000..5befdf7688
+--- /dev/null
++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+@@ -0,0 +1,102 @@
++## @file\r
++# NetworkPkgHostTest DSC file used to build host-based unit tests.\r
++#\r
++# Copyright (c) Microsoft Corporation.<BR>\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++#\r
++##\r
++[Defines]\r
++  PLATFORM_NAME           = NetworkPkgHostTest\r
++  PLATFORM_GUID           = 3b68324e-fc07-4d49-9520-9347ede65879\r
++  PLATFORM_VERSION        = 0.1\r
++  DSC_SPECIFICATION       = 0x00010005\r
++  OUTPUT_DIRECTORY        = Build/NetworkPkg/HostTest\r
++  SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64\r
++  BUILD_TARGETS           = NOOPT\r
++  SKUID_IDENTIFIER        = DEFAULT\r
++  \r
++!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc\r
++[Packages]\r
++  MdePkg/MdePkg.dec\r
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
++\r
++[Components]\r
++  #\r
++  # Build HOST_APPLICATION that tests NetworkPkg\r
++  #\r
++  NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf\r
++\r
++# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.\r
++[LibraryClasses]\r
++  NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf\r
++  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
++  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
++  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
++  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
++  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
++  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
++  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
++  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
++  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
++  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
++  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
++  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
++  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
++  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf\r
++  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf\r
++  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
++  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
++  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
++  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
++  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
++  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf\r
++  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf\r
++  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf\r
++!ifdef CONTINUOUS_INTEGRATION\r
++  BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf\r
++  TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf\r
++!else\r
++  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
++  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
++  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf\r
++!endif\r
++  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf\r
++  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf\r
++  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf\r
++  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf\r
++  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf\r
++\r
++!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022\r
++[LibraryClasses.X64]\r
++  # Provide StackCookie support lib so that we can link to /GS exports for VS builds\r
++  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf\r
++  NULL|MdePkg/Library/BaseBinSecurityLibRng/BaseBinSecurityLibRng.inf\r
++!endif\r
++\r
++[LibraryClasses.common.UEFI_DRIVER]\r
++  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
++  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf\r
++  DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf\r
++[LibraryClasses.common.UEFI_APPLICATION]\r
++  DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf\r
++  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf\r
++[LibraryClasses.ARM, LibraryClasses.AARCH64]\r
++  #\r
++  # It is not possible to prevent ARM compiler calls to generic intrinsic functions.\r
++  # This library provides the instrinsic functions generated by a given compiler.\r
++  # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.\r
++  #\r
++  # MU_CHANGE Start\r
++!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019\r
++  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf\r
++!endif\r
++  # MU_CHANGE End\r
++  NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf\r
++[LibraryClasses.ARM]\r
++  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf\r
++[LibraryClasses.RISCV64]\r
++  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf\r
++  \r
++[PcdsFixedAtBuild]\r
++  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2\r
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
+\ No newline at end of file
+-- 
+2.41.0
+
+
+From 9613e15be77676e119291f28ae46cb13bf37f235 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 15 Dec 2023 11:26:47 -0800
+Subject: [PATCH 03/12] SECURITY PATCH TCBZ4534 - CVE-2023-45229 - Patch
+
+---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 134 ++++++++++++++++++---
+ NetworkPkg/Dhcp6Dxe/Dhcp6Io.c   | 202 ++++++++++++++++++++++----------
+ 2 files changed, 257 insertions(+), 79 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+index b552331767..5247b324ac 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
+@@ -45,6 +45,20 @@ typedef struct _DHCP6_INSTANCE  DHCP6_INSTANCE;
+ #define DHCP6_SERVICE_SIGNATURE   SIGNATURE_32 ('D', 'H', '6', 'S')\r
+ #define DHCP6_INSTANCE_SIGNATURE  SIGNATURE_32 ('D', 'H', '6', 'I')\r
\r
++#define DHCP6_PACKET_ALL        0\r
++#define DHCP6_PACKET_STATEFUL   1\r
++#define DHCP6_PACKET_STATELESS  2\r
++\r
++#define DHCP6_BASE_PACKET_SIZE  1024\r
++\r
++#define DHCP6_PORT_CLIENT  546\r
++#define DHCP6_PORT_SERVER  547\r
++\r
++#define DHCP_CHECK_MEDIA_WAITING_TIME  EFI_TIMER_PERIOD_SECONDS(20)\r
++\r
++#define DHCP6_INSTANCE_FROM_THIS(Instance)  CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)\r
++#define DHCP6_SERVICE_FROM_THIS(Service)    CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)\r
++\r
+ //\r
+ // For more information on DHCP options see RFC 8415, Section 21.1\r
+ // \r
+@@ -59,8 +73,8 @@ typedef struct _DHCP6_INSTANCE  DHCP6_INSTANCE;
+ //    |                      (option-len octets)                      |\r
+ //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+ //\r
+-#define DHCP6_SIZE_OF_OPT_CODE    (sizeof(UINT16))\r
+-#define DHCP6_SIZE_OF_OPT_LEN     (sizeof(UINT16))\r
++#define DHCP6_SIZE_OF_OPT_CODE (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode))\r
++#define DHCP6_SIZE_OF_OPT_LEN (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))\r
\r
+ // Combined size of Code and Length\r
+ #define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN  (DHCP6_SIZE_OF_OPT_CODE + \\r
+@@ -72,31 +86,121 @@ STATIC_ASSERT (
+                );\r
\r
+ // Offset to the length is just past the code\r
+-#define DHCP6_OPT_LEN_OFFSET(a)  (a + DHCP6_SIZE_OF_OPT_CODE)\r
++#define DHCP6_OFFSET_OF_OPT_LEN(a)  (a + DHCP6_SIZE_OF_OPT_CODE)\r
+ STATIC_ASSERT (\r
+-               DHCP6_OPT_LEN_OFFSET (0) == 2,\r
++               DHCP6_OFFSET_OF_OPT_LEN (0) == 2,\r
+                "Offset of length is + 2 past start of option"\r
+                );\r
\r
+-#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)\r
++#define DHCP6_OFFSET_OF_OPT_DATA(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)\r
+ STATIC_ASSERT (\r
+-               DHCP6_OPT_DATA_OFFSET(0) == 4,\r
++               DHCP6_OFFSET_OF_OPT_DATA(0) == 4,\r
+                "Offset to option data should be +4 from start of option"\r
+                );\r
++//\r
++// Identity Association options (both NA (Non-Temporary) and TA (Temporary Association))\r
++// are defined in RFC 8415 and are a deriviation of a TLV stucture\r
++// For more information on IA_NA see Section 21.4\r
++// For more information on IA_TA see Section 21.5\r
++//\r
++//\r
++//  The format of IA_NA and IA_TA option:\r
++//\r
++//     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\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |          OPTION_IA_NA         |          option-len           |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |                        IAID (4 octets)                        |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |                        T1 (only for IA_NA)                    |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |                        T2 (only for IA_NA)                    |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |                                                               |\r
++//    .                  IA_NA-options/IA_TA-options                  .\r
++//    .                                                               .\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//\r
++#define DHCP6_SIZE_OF_IAID           (sizeof(UINT32))\r
++#define DHCP6_SIZE_OF_TIME_INTERVAL  (sizeof(UINT32))\r
\r
+-#define DHCP6_PACKET_ALL        0\r
+-#define DHCP6_PACKET_STATEFUL   1\r
+-#define DHCP6_PACKET_STATELESS  2\r
++// Combined size of IAID, T1, and T2\r
++#define DHCP6_SIZE_OF_COMBINED_IAID_T1_T2  (DHCP6_SIZE_OF_IAID +  \\r
++                                            DHCP6_SIZE_OF_TIME_INTERVAL + \\r
++                                            DHCP6_SIZE_OF_TIME_INTERVAL)\r
++STATIC_ASSERT (\r
++               DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 == 12,\r
++               "Combined size of IAID, T1, T2 must be 12 per RFC 8415"\r
++               );\r
\r
+-#define DHCP6_BASE_PACKET_SIZE  1024\r
++// This is the size of IA_TA without options\r
++#define DHCP6_MIN_SIZE_OF_IA_TA  (DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \\r
++                                  DHCP6_SIZE_OF_IAID)\r
++STATIC_ASSERT (\r
++               DHCP6_MIN_SIZE_OF_IA_TA == 8,\r
++               "Minimum combined size of IA_TA per RFC 8415"\r
++               );\r
\r
+-#define DHCP6_PORT_CLIENT  546\r
+-#define DHCP6_PORT_SERVER  547\r
++// Offset to a IA_TA inner option\r
++#define DHCP6_OFFSET_OF_IA_TA_INNER_OPT(a)  (a + DHCP6_MIN_SIZE_OF_IA_TA)\r
++STATIC_ASSERT (\r
++               DHCP6_OFFSET_OF_IA_TA_INNER_OPT (0) == 8,\r
++               "Offset of IA_TA Inner option is + 8 past start of option"\r
++               );\r
\r
+-#define DHCP_CHECK_MEDIA_WAITING_TIME  EFI_TIMER_PERIOD_SECONDS(20)\r
++// This is the size of IA_NA without options (16)\r
++#define DHCP6_MIN_SIZE_OF_IA_NA  DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \\r
++                                 DHCP6_SIZE_OF_COMBINED_IAID_T1_T2\r
++STATIC_ASSERT (\r
++               DHCP6_MIN_SIZE_OF_IA_NA == 16,\r
++               "Minimum combined size of IA_TA per RFC 8415"\r
++               );\r
\r
+-#define DHCP6_INSTANCE_FROM_THIS(Instance)  CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)\r
+-#define DHCP6_SERVICE_FROM_THIS(Service)    CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)\r
++#define DHCP6_OFFSET_OF_IA_NA_INNER_OPT(a)  (a + DHCP6_MIN_SIZE_OF_IA_NA)\r
++STATIC_ASSERT (\r
++               DHCP6_OFFSET_OF_IA_NA_INNER_OPT (0) == 16,\r
++               "Offset of IA_NA Inner option is + 16 past start of option"\r
++               );\r
++\r
++#define DHCP6_OFFSET_OF_IA_NA_T1(a)  (a + \\r
++                                   DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \\r
++                                   DHCP6_SIZE_OF_IAID)\r
++STATIC_ASSERT (\r
++               DHCP6_OFFSET_OF_IA_NA_T1 (0) == 8,\r
++               "Offset of IA_NA Inner option is + 8 past start of option"\r
++               );\r
++\r
++#define DHCP6_OFFSET_OF_IA_NA_T2(a)  (a + \\r
++                                   DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN +\\r
++                                   DHCP6_SIZE_OF_IAID + \\r
++                                   DHCP6_SIZE_OF_TIME_INTERVAL)\r
++STATIC_ASSERT (\r
++               DHCP6_OFFSET_OF_IA_NA_T2 (0) == 12,\r
++               "Offset of IA_NA Inner option is + 12 past start of option"\r
++               );\r
++\r
++//\r
++// For more information see RFC 8415 Section 21.13\r
++//\r
++// The format of the Status Code Option:\r
++//\r
++//     0                   1                   2                   3\r
++//     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\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |       OPTION_STATUS_CODE      |         option-len            |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |          status-code          |                               |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |\r
++//    .                                                               .\r
++//    .                        status-message                         .\r
++//    .                                                               .\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//\r
++#define DHCP6_OFFSET_OF_STATUS_CODE(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)\r
++STATIC_ASSERT (\r
++               DHCP6_OFFSET_OF_STATUS_CODE (0) == 4,\r
++               "Offset of status is + 4 past start of option"\r
++               );\r
\r
+ extern EFI_IPv6_ADDRESS    mAllDhcpRelayAndServersAddress;\r
+ extern EFI_DHCP6_PROTOCOL  gDhcp6ProtocolTemplate;\r
+diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+index 1401910950..f96b4c7962 100644
+--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+@@ -598,8 +598,9 @@ Dhcp6UpdateIaInfo (
+   // The inner options still start with 2 bytes option-code and 2 bytes option-len.\r
+   //\r
+   if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {\r
+-    T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 8)));\r
+-    T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 12)));\r
++\r
++    T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1(Option))));\r
++    T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2(Option))));\r
+     //\r
+     // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2,\r
+     // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes\r
+@@ -609,13 +610,14 @@ Dhcp6UpdateIaInfo (
+       return EFI_DEVICE_ERROR;\r
+     }\r
\r
+-    IaInnerOpt = Option + 16;\r
+-    IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 12);\r
++    IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT(Option);\r
++    IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2);\r
+   } else {\r
+     T1         = 0;\r
+     T2         = 0;\r
+-    IaInnerOpt = Option + 8;\r
+-    IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 4);\r
++\r
++    IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT(Option);\r
++    IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option)))) - DHCP6_SIZE_OF_IAID);\r
+   }\r
\r
+   //\r
+@@ -641,7 +643,7 @@ Dhcp6UpdateIaInfo (
+   Option  = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);\r
\r
+   if (Option != NULL) {\r
+-    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));\r
++    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option))));\r
+     if (StsCode != Dhcp6StsSuccess) {\r
+       return EFI_DEVICE_ERROR;\r
+     }\r
+@@ -661,6 +663,88 @@ Dhcp6UpdateIaInfo (
+   return Status;\r
+ }\r
\r
++/*\r
++  Seeks the Inner Options from a DHCP6 Option\r
++\r
++  @param[in]  IaType          The type of the IA option.\r
++  @param[in]  Option          The pointer to the DHCP6 Option.\r
++  @param[in]  OptionLen       The length of the DHCP6 Option.\r
++  @param[out] IaInnerOpt      The pointer to the IA inner option.\r
++  @param[out] IaInnerLen      The length of the IA inner option.\r
++\r
++  @retval EFI_SUCCESS         Seek the inner option successfully.\r
++  @retval EFI_DEVICE_ERROR    The OptionLen is invalid. On Error,\r
++                              the pointers are not modified\r
++*/\r
++EFI_STATUS\r
++Dhcp6SeekInnerOptionSafe (\r
++  IN  UINT16  IaType,\r
++  IN  UINT8   *Option,\r
++  IN  UINT32  OptionLen,\r
++  OUT UINT8   **IaInnerOpt,\r
++  OUT UINT16  *IaInnerLen\r
++  )\r
++{\r
++ \r
++  UINT16  IaInnerLenTmp;\r
++  UINT8   *IaInnerOptTmp;\r
++\r
++  if (Option == NULL) {\r
++    ASSERT (Option != NULL);\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  if (IaInnerOpt == NULL) {\r
++    ASSERT (IaInnerOpt != NULL);\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  if (IaInnerLen == NULL) {\r
++    ASSERT (IaInnerLen != NULL);\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  if (IaType == Dhcp6OptIana) {\r
++    // Verify we have a fully formed IA_NA\r
++    if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) {\r
++      return EFI_DEVICE_ERROR;\r
++    }\r
++    \r
++    //\r
++    IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT(Option);\r
++\r
++    // Verify the IaInnerLen is valid.\r
++    IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN(Option)));\r
++    if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) {\r
++      return EFI_DEVICE_ERROR;\r
++    }\r
++\r
++    IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2;\r
++  } else if (IaType == Dhcp6OptIata) {\r
++    // Verify the OptionLen is valid.\r
++    if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) {\r
++      return EFI_DEVICE_ERROR;\r
++    }\r
++\r
++    IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT(Option);\r
++\r
++    // Verify the IaInnerLen is valid.\r
++    IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option))));\r
++    if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) {\r
++      return EFI_DEVICE_ERROR;\r
++    }\r
++\r
++    IaInnerLenTmp -= DHCP6_SIZE_OF_IAID;\r
++  } else {\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  *IaInnerOpt = IaInnerOptTmp;\r
++  *IaInnerLen = IaInnerLenTmp;\r
++\r
++  return EFI_SUCCESS;\r
++}\r
++\r
+ /**\r
+   Seek StatusCode Option in package. A Status Code option may appear in the\r
+   options field of a DHCP message and/or in the options field of another option.\r
+@@ -684,6 +768,12 @@ Dhcp6SeekStsOption (
+   UINT8   *IaInnerOpt;\r
+   UINT16  IaInnerLen;\r
+   UINT16  StsCode;\r
++  UINT32  OptionLen;\r
++\r
++  // OptionLen is the length of the Options excluding the DHCP header.\r
++  // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last\r
++  // byte of the Option[] field.\r
++  OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header);\r
\r
+   //\r
+   // Seek StatusCode option directly in DHCP message body. That is, search in\r
+@@ -691,12 +781,12 @@ Dhcp6SeekStsOption (
+   //\r
+   *Option = Dhcp6SeekOption (\r
+               Packet->Dhcp6.Option,\r
+-              Packet->Length - 4,\r
++              OptionLen,\r
+               Dhcp6OptStatusCode\r
+               );\r
\r
+   if (*Option != NULL) {\r
+-    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));\r
++    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE(*Option))));\r
+     if (StsCode != Dhcp6StsSuccess) {\r
+       return EFI_DEVICE_ERROR;\r
+     }\r
+@@ -707,7 +797,7 @@ Dhcp6SeekStsOption (
+   //\r
+   *Option = Dhcp6SeekIaOption (\r
+               Packet->Dhcp6.Option,\r
+-              Packet->Length - sizeof (EFI_DHCP6_HEADER),\r
++              OptionLen,\r
+               &Instance->Config->IaDescriptor\r
+               );\r
+   if (*Option == NULL) {\r
+@@ -715,52 +805,35 @@ Dhcp6SeekStsOption (
+   }\r
\r
+   //\r
+-  // The format of the IA_NA option is:\r
++  // Calculate the distance from Packet->Dhcp6.Option to the IA option.\r
+   //\r
+-  //     0                   1                   2                   3\r
+-  //     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\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |          OPTION_IA_NA         |          option-len           |\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |                        IAID (4 octets)                        |\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |                              T1                               |\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |                              T2                               |\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |                                                               |\r
+-  //    .                         IA_NA-options                         .\r
+-  //    .                                                               .\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++  // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is\r
++  // the size of the whole packet, including the DHCP header, and Packet->Length\r
++  // is the length of the DHCP message body, excluding the DHCP header.\r
+   //\r
+-  // The format of the IA_TA option is:\r
++  // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of\r
++  // DHCP6 option area to the start of the IA option.\r
+   //\r
+-  //     0                   1                   2                   3\r
+-  //     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\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |         OPTION_IA_TA          |          option-len           |\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |                        IAID (4 octets)                        |\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
+-  //    |                                                               |\r
+-  //    .                         IA_TA-options                         .\r
+-  //    .                                                               .\r
+-  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++  // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the\r
++  // IA option to the end of the DHCP6 option area, thus subtract the space\r
++  // up until this option\r
+   //\r
++  OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option);\r
\r
+   //\r
+-  // sizeof (option-code + option-len + IaId)           = 8\r
+-  // sizeof (option-code + option-len + IaId + T1)      = 12\r
+-  // sizeof (option-code + option-len + IaId + T1 + T2) = 16\r
++  // Seek the inner option\r
+   //\r
+-  // The inner options still start with 2 bytes option-code and 2 bytes option-len.\r
+-  //\r
+-  if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {\r
+-    IaInnerOpt = *Option + 16;\r
+-    IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 12);\r
+-  } else {\r
+-    IaInnerOpt = *Option + 8;\r
+-    IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 4);\r
++  if (EFI_ERROR (\r
++        Dhcp6SeekInnerOptionSafe (\r
++          Instance->Config->IaDescriptor.Type,\r
++          *Option,\r
++          OptionLen,\r
++          &IaInnerOpt,\r
++          &IaInnerLen\r
++          )\r
++        ))\r
++  {\r
++    return EFI_DEVICE_ERROR;\r
+   }\r
\r
+   //\r
+@@ -784,7 +857,7 @@ Dhcp6SeekStsOption (
+   //\r
+   *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);\r
+   if (*Option != NULL) {\r
+-    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));\r
++    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE(*Option)))));\r
+     if (StsCode != Dhcp6StsSuccess) {\r
+       return EFI_DEVICE_ERROR;\r
+     }\r
+@@ -1105,7 +1178,7 @@ Dhcp6SendRequestMsg (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              Instance->AdSelect->Dhcp6.Option,\r
+-             Instance->AdSelect->Length - 4,\r
++             Instance->AdSelect->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptServerId\r
+              );\r
+   if (Option == NULL) {\r
+@@ -1289,7 +1362,7 @@ Dhcp6SendDeclineMsg (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              LastReply->Dhcp6.Option,\r
+-             LastReply->Length - 4,\r
++             LastReply->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptServerId\r
+              );\r
+   if (Option == NULL) {\r
+@@ -1448,7 +1521,7 @@ Dhcp6SendReleaseMsg (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              LastReply->Dhcp6.Option,\r
+-             LastReply->Length - 4,\r
++             LastReply->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptServerId\r
+              );\r
+   if (Option == NULL) {\r
+@@ -1674,7 +1747,7 @@ Dhcp6SendRenewRebindMsg (
\r
+     Option = Dhcp6SeekOption (\r
+                LastReply->Dhcp6.Option,\r
+-               LastReply->Length - 4,\r
++               LastReply->Length - sizeof(EFI_DHCP6_HEADER),\r
+                Dhcp6OptServerId\r
+                );\r
+     if (Option == NULL) {\r
+@@ -2210,7 +2283,7 @@ Dhcp6HandleReplyMsg (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              Packet->Dhcp6.Option,\r
+-             Packet->Length - 4,\r
++             Packet->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptRapidCommit\r
+              );\r
\r
+@@ -2356,7 +2429,7 @@ Dhcp6HandleReplyMsg (
+     //\r
+     // Any error status code option is found.\r
+     //\r
+-    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));\r
++    StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE(Option)))));\r
+     switch (StsCode) {\r
+       case Dhcp6StsUnspecFail:\r
+         //\r
+@@ -2489,7 +2562,7 @@ Dhcp6SelectAdvertiseMsg (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              AdSelect->Dhcp6.Option,\r
+-             AdSelect->Length - 4,\r
++             AdSelect->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptServerUnicast\r
+              );\r
\r
+@@ -2500,7 +2573,7 @@ Dhcp6SelectAdvertiseMsg (
+       return EFI_OUT_OF_RESOURCES;\r
+     }\r
\r
+-    CopyMem (Instance->Unicast, Option + 4, sizeof (EFI_IPv6_ADDRESS));\r
++    CopyMem (Instance->Unicast, DHCP6_OFFSET_OF_OPT_DATA(Option), sizeof (EFI_IPv6_ADDRESS));\r
+   }\r
\r
+   //\r
+@@ -2553,7 +2626,7 @@ Dhcp6HandleAdvertiseMsg (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              Packet->Dhcp6.Option,\r
+-             Packet->Length - 4,\r
++             Packet->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptRapidCommit\r
+              );\r
\r
+@@ -2647,7 +2720,8 @@ Dhcp6HandleAdvertiseMsg (
+       CopyMem (Instance->AdSelect, Packet, Packet->Size);\r
\r
+       if (Option != NULL) {\r
+-        Instance->AdPref = *(Option + 4);\r
++        Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA(Option));\r
++\r
+       }\r
+     } else {\r
+       //\r
+@@ -2716,11 +2790,11 @@ Dhcp6HandleStateful (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              Packet->Dhcp6.Option,\r
+-             Packet->Length - 4,\r
++             Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,\r
+              Dhcp6OptClientId\r
+              );\r
\r
+-  if ((Option == NULL) || (CompareMem (Option + 4, ClientId->Duid, ClientId->Length) != 0)) {\r
++  if ((Option == NULL) || (CompareMem (DHCP6_OFFSET_OF_OPT_DATA(Option), ClientId->Duid, ClientId->Length) != 0)) {\r
+     goto ON_CONTINUE;\r
+   }\r
\r
+@@ -2729,7 +2803,7 @@ Dhcp6HandleStateful (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              Packet->Dhcp6.Option,\r
+-             Packet->Length - 4,\r
++             Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,\r
+              Dhcp6OptServerId\r
+              );\r
\r
+@@ -2834,7 +2908,7 @@ Dhcp6HandleStateless (
+   //\r
+   Option = Dhcp6SeekOption (\r
+              Packet->Dhcp6.Option,\r
+-             Packet->Length - 4,\r
++             Packet->Length - sizeof(EFI_DHCP6_HEADER),\r
+              Dhcp6OptServerId\r
+              );\r
\r
+-- 
+2.41.0
+
+
+From ac0130907b8a88cca3c4d8eb590f3b4aa33133d8 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 15 Dec 2023 13:31:38 -0800
+Subject: [PATCH 04/12] SECURITY PATCH TCBZ4534 - CVE-2023-45229 - Host Based
+ Unit Test
+
+---
+ .../GoogleTest/Dhcp6DxeGoogleTest.cpp         |  54 +-
+ .../GoogleTest/Dhcp6DxeGoogleTest.inf         |  86 +--
+ .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 631 ++++++++++++++----
+ .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h   |  58 ++
+ NetworkPkg/Test/NetworkPkgHostTest.dsc        | 204 +++---
+ 5 files changed, 726 insertions(+), 307 deletions(-)
+ create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
+
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+index b1fe72e195..36fd708cfc 100644
+--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
+@@ -1,27 +1,27 @@
+-/** @file\r
+-  Acts as the main entry point for the tests for the Dhcp6Dxe module.\r
+-\r
+-  Copyright (c) Microsoft Corporation\r
+-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-**/\r
+-#include <gtest/gtest.h>\r
+-\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-// Add test files here\r
+-// Google Test will only pick up the tests from the files that are included\r
+-// here.\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-#include "Dhcp6IoGoogleTest.cpp"\r
+-\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-// Run the tests\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-int\r
+-main (\r
+-  int   argc,\r
+-  char  *argv[]\r
+-  )\r
+-{\r
+-  testing::InitGoogleTest (&argc, argv);\r
+-  return RUN_ALL_TESTS ();\r
+-}\r
++/** @file
++  Acts as the main entry point for the tests for the Dhcp6Dxe module.
++
++  Copyright (c) Microsoft Corporation
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++////////////////////////////////////////////////////////////////////////////////
++// Add test files here
++// Google Test will only pick up the tests from the files that are included
++// here.
++////////////////////////////////////////////////////////////////////////////////
++#include "Dhcp6IoGoogleTest.cpp"
++
++////////////////////////////////////////////////////////////////////////////////
++// Run the tests
++////////////////////////////////////////////////////////////////////////////////
++int
++main (
++  int   argc,
++  char  *argv[]
++  )
++{
++  testing::InitGoogleTest (&argc, argv);
++  return RUN_ALL_TESTS ();
++}
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+index c7ec42b322..b74497b6b3 100644
+--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+@@ -1,44 +1,44 @@
+-## @file\r
+-# Unit test suite for the Dhcp6Dxe using Google Test\r
+-#\r
+-# Copyright (c) Microsoft Corporation.<BR>\r
+-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-##\r
+-[Defines]\r
+-  INF_VERSION         = 0x00010017\r
+-  BASE_NAME           = Dhcp6DxeGoogleTest\r
+-  FILE_GUID           = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9\r
+-  VERSION_STRING      = 1.0\r
+-  MODULE_TYPE         = HOST_APPLICATION\r
+-#\r
+-# The following information is for reference only and not required by the build tools.\r
+-#\r
+-#  VALID_ARCHITECTURES           = IA32 X64 AARCH64\r
+-#\r
+-[Sources]\r
+-  Dhcp6DxeGoogleTest.cpp\r
+-  Dhcp6IoGoogleTest.cpp\r
+-  ../Dhcp6Io.c\r
+-  ../Dhcp6Utility.c\r
+-\r
+-\r
+-[Packages]\r
+-  MdePkg/MdePkg.dec\r
+-  MdeModulePkg/MdeModulePkg.dec\r
+-  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
+-  NetworkPkg/NetworkPkg.dec\r
+-\r
+-[LibraryClasses]\r
+-  GoogleTestLib\r
+-  DebugLib\r
+-  NetLib\r
+-  PcdLib\r
+-\r
+-[Protocols]\r
+-  gEfiDhcp6ServiceBindingProtocolGuid\r
+-\r
+-[Pcd]\r
+-  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType\r
+-\r
+-[Guids]\r
++## @file
++# Unit test suite for the Dhcp6Dxe using Google Test
++#
++# Copyright (c) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++[Defines]
++  INF_VERSION         = 0x00010017
++  BASE_NAME           = Dhcp6DxeGoogleTest
++  FILE_GUID           = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9
++  VERSION_STRING      = 1.0
++  MODULE_TYPE         = HOST_APPLICATION
++#
++# The following information is for reference only and not required by the build tools.
++#
++#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
++#
++[Sources]
++  Dhcp6DxeGoogleTest.cpp
++  Dhcp6IoGoogleTest.cpp
++  ../Dhcp6Io.c
++  ../Dhcp6Utility.c
++
++
++[Packages]
++  MdePkg/MdePkg.dec
++  MdeModulePkg/MdeModulePkg.dec
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++  NetworkPkg/NetworkPkg.dec
++
++[LibraryClasses]
++  GoogleTestLib
++  DebugLib
++  NetLib
++  PcdLib
++
++[Protocols]
++  gEfiDhcp6ServiceBindingProtocolGuid
++
++[Pcd]
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
++
++[Guids]
+   gZeroGuid  
+\ No newline at end of file
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+index dad6a42b12..31e848543d 100644
+--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+@@ -7,12 +7,13 @@
+ #include <gtest/gtest.h>\r
\r
+ extern "C" {\r
+-  #include <Uefi.h>\r
+-  #include <Library/BaseLib.h>\r
+-  #include <Library/DebugLib.h>\r
+-  #include <Library/BaseMemoryLib.h>\r
+-  #include "../Dhcp6Impl.h"\r
+-  #include "../Dhcp6Utility.h"\r
++#include <Uefi.h>\r
++#include <Library/BaseLib.h>\r
++#include <Library/DebugLib.h>\r
++#include <Library/BaseMemoryLib.h>\r
++#include "../Dhcp6Impl.h"\r
++#include "../Dhcp6Utility.h"\r
++#include "Dhcp6IoGoogleTest.h"\r
+ }\r
\r
+ ////////////////////////////////////////////////////////////////////////\r
+@@ -21,7 +22,35 @@ extern "C" {
\r
+ #define DHCP6_PACKET_MAX_LEN  1500\r
\r
++// This definition is used by this test but is also required to compile\r
++// by Dhcp6Io.c\r
++#define DHCPV6_OPTION_IA_NA  3\r
++#define DHCPV6_OPTION_IA_TA  4\r
++\r
++#define SEARCH_PATTERN      0xDEADC0DE\r
++#define SEARCH_PATTERN_LEN  sizeof(SEARCH_PATTERN)\r
++\r
+ ////////////////////////////////////////////////////////////////////////\r
++// Test structures for IA_NA and IA_TA options\r
++////////////////////////////////////////////////////////////////////////\r
++typedef struct {\r
++  UINT16    Code;\r
++  UINT16    Len;\r
++  UINT32    IAID;\r
++} DHCPv6_OPTION;\r
++\r
++typedef struct {\r
++  DHCPv6_OPTION    Header;\r
++  UINT32           T1;\r
++  UINT32           T2;\r
++  UINT8            InnerOptions[0];\r
++} DHCPv6_OPTION_IA_NA;\r
++\r
++typedef struct {\r
++  DHCPv6_OPTION    Header;\r
++  UINT8            InnerOptions[0];\r
++} DHCPv6_OPTION_IA_TA;\r
++\r
+ ////////////////////////////////////////////////////////////////////////\r
+ // Symbol Definitions\r
+ // These functions are not directly under test - but required to compile\r
+@@ -65,33 +94,33 @@ UdpIoRecvDatagram (
\r
+ class Dhcp6AppendOptionTest : public ::testing::Test {\r
+ public:\r
+-  UINT8 *Buffer = NULL;\r
+-  EFI_DHCP6_PACKET *Packet;\r
++UINT8 *Buffer = NULL;\r
++EFI_DHCP6_PACKET *Packet;\r
\r
+ protected:\r
+-  // Add any setup code if needed\r
+-  virtual void\r
+-  SetUp (\r
+-    )\r
+-  {\r
+-    // Initialize any resources or variables\r
+-    Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
+-    ASSERT_NE (Buffer, (UINT8 *)NULL);\r
+-\r
+-    Packet       = (EFI_DHCP6_PACKET *)Buffer;\r
+-    Packet->Size = DHCP6_PACKET_MAX_LEN;\r
+-  }\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++  // Initialize any resources or variables\r
++  Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
++  ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++\r
++  Packet       = (EFI_DHCP6_PACKET *)Buffer;\r
++  Packet->Size = DHCP6_PACKET_MAX_LEN;\r
++}\r
\r
+-  // Add any cleanup code if needed\r
+-  virtual void\r
+-  TearDown (\r
+-    )\r
+-  {\r
+-    // Clean up any resources or variables\r
+-    if (Buffer != NULL) {\r
+-      FreePool (Buffer);\r
+-    }\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++  // Clean up any resources or variables\r
++  if (Buffer != NULL) {\r
++    FreePool (Buffer);\r
+   }\r
++}\r
+ };\r
\r
+ // Test Description:\r
+@@ -109,12 +138,12 @@ TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) {
+   Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;\r
\r
+   Status = Dhcp6AppendOption (\r
+-             Dhcp6AppendOptionTest::Packet,\r
+-             &Cursor,\r
+-             HTONS (Dhcp6OptServerId),\r
+-             UntrustedDuid->Length,\r
+-             UntrustedDuid->Duid\r
+-             );\r
++                              Dhcp6AppendOptionTest::Packet,\r
++                              &Cursor,\r
++                              HTONS (Dhcp6OptServerId),\r
++                              UntrustedDuid->Length,\r
++                              UntrustedDuid->Duid\r
++                              );\r
\r
+   ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
+ }\r
+@@ -141,12 +170,12 @@ TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
+   Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;\r
\r
+   Status = Dhcp6AppendOption (\r
+-             Dhcp6AppendOptionTest::Packet,\r
+-             &Cursor,\r
+-             HTONS (Dhcp6OptServerId),\r
+-             UntrustedDuid->Length,\r
+-             UntrustedDuid->Duid\r
+-             );\r
++                              Dhcp6AppendOptionTest::Packet,\r
++                              &Cursor,\r
++                              HTONS (Dhcp6OptServerId),\r
++                              UntrustedDuid->Length,\r
++                              UntrustedDuid->Duid\r
++                              );\r
\r
+   ASSERT_EQ (Status, EFI_SUCCESS);\r
\r
+@@ -163,34 +192,34 @@ TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
\r
+ class Dhcp6AppendETOptionTest : public ::testing::Test {\r
+ public:\r
+-  UINT8 *Buffer = NULL;\r
+-  EFI_DHCP6_PACKET *Packet;\r
++UINT8 *Buffer = NULL;\r
++EFI_DHCP6_PACKET *Packet;\r
\r
+ protected:\r
+-  // Add any setup code if needed\r
+-  virtual void\r
+-  SetUp (\r
+-    )\r
+-  {\r
+-    // Initialize any resources or variables\r
+-    Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
+-    ASSERT_NE (Buffer, (UINT8 *)NULL);\r
+-\r
+-    Packet         = (EFI_DHCP6_PACKET *)Buffer;\r
+-    Packet->Size   = DHCP6_PACKET_MAX_LEN;\r
+-    Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
+-  }\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++  // Initialize any resources or variables\r
++  Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
++  ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++\r
++  Packet         = (EFI_DHCP6_PACKET *)Buffer;\r
++  Packet->Size   = DHCP6_PACKET_MAX_LEN;\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++}\r
\r
+-  // Add any cleanup code if needed\r
+-  virtual void\r
+-  TearDown (\r
+-    )\r
+-  {\r
+-    // Clean up any resources or variables\r
+-    if (Buffer != NULL) {\r
+-      FreePool (Buffer);\r
+-    }\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++  // Clean up any resources or variables\r
++  if (Buffer != NULL) {\r
++    FreePool (Buffer);\r
+   }\r
++}\r
+ };\r
\r
+ // Test Description:\r
+@@ -208,11 +237,11 @@ TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {
+   Packet->Length = Packet->Size - 2;\r
\r
+   Status = Dhcp6AppendETOption (\r
+-             Dhcp6AppendETOptionTest::Packet,\r
+-             &Cursor,\r
+-             &Instance, // Instance is not used in this function\r
+-             &ElapsedTime\r
+-             );\r
++                                Dhcp6AppendETOptionTest::Packet,\r
++                                &Cursor,\r
++                                &Instance, // Instance is not used in this function\r
++                                &ElapsedTime\r
++                                );\r
\r
+   // verify that we error out because the packet is too small for the option header\r
+   ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
+@@ -238,11 +267,11 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
+   OriginalLength = Packet->Length;\r
\r
+   Status = Dhcp6AppendETOption (\r
+-             Dhcp6AppendETOptionTest::Packet,\r
+-             &Cursor,\r
+-             &Instance, // Instance is not used in this function\r
+-             &ElapsedTime\r
+-             );\r
++                                Dhcp6AppendETOptionTest::Packet,\r
++                                &Cursor,\r
++                                &Instance, // Instance is not used in this function\r
++                                &ElapsedTime\r
++                                );\r
\r
+   // verify that the status is EFI_SUCCESS\r
+   ASSERT_EQ (Status, EFI_SUCCESS);\r
+@@ -260,46 +289,46 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
\r
+ class Dhcp6AppendIaOptionTest : public ::testing::Test {\r
+ public:\r
+-  UINT8 *Buffer = NULL;\r
+-  EFI_DHCP6_PACKET *Packet;\r
+-  EFI_DHCP6_IA *Ia;\r
++UINT8 *Buffer = NULL;\r
++EFI_DHCP6_PACKET *Packet;\r
++EFI_DHCP6_IA *Ia;\r
\r
+ protected:\r
+-  // Add any setup code if needed\r
+-  virtual void\r
+-  SetUp (\r
+-    )\r
+-  {\r
+-    // Initialize any resources or variables\r
+-    Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
+-    ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++  // Initialize any resources or variables\r
++  Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);\r
++  ASSERT_NE (Buffer, (UINT8 *)NULL);\r
++\r
++  Packet       = (EFI_DHCP6_PACKET *)Buffer;\r
++  Packet->Size = DHCP6_PACKET_MAX_LEN;\r
\r
+-    Packet       = (EFI_DHCP6_PACKET *)Buffer;\r
+-    Packet->Size = DHCP6_PACKET_MAX_LEN;\r
++  Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);\r
++  ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);\r
\r
+-    Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);\r
+-    ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);\r
++  CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));\r
++  CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));\r
\r
+-    CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));\r
+-    CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));\r
++  Ia->IaAddressCount = 2;\r
++}\r
\r
+-    Ia->IaAddressCount = 2;\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++  // Clean up any resources or variables\r
++  if (Buffer != NULL) {\r
++    FreePool (Buffer);\r
+   }\r
\r
+-  // Add any cleanup code if needed\r
+-  virtual void\r
+-  TearDown (\r
+-    )\r
+-  {\r
+-    // Clean up any resources or variables\r
+-    if (Buffer != NULL) {\r
+-      FreePool (Buffer);\r
+-    }\r
+-\r
+-    if (Ia != NULL) {\r
+-      FreePool (Ia);\r
+-    }\r
++  if (Ia != NULL) {\r
++    FreePool (Ia);\r
+   }\r
++}\r
+ };\r
\r
+ // Test Description:\r
+@@ -317,13 +346,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) {
+   Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
\r
+   Status = Dhcp6AppendIaOption (\r
+-             Dhcp6AppendIaOptionTest::Packet,\r
+-             &Cursor,\r
+-             Ia,\r
+-             0x12345678,\r
+-             0x11111111,\r
+-             Dhcp6OptIana\r
+-             );\r
++                                Dhcp6AppendIaOptionTest::Packet,\r
++                                &Cursor,\r
++                                Ia,\r
++                                0x12345678,\r
++                                0x11111111,\r
++                                Dhcp6OptIana\r
++                                );\r
\r
+   // verify that we error out because the packet is too small for the option header\r
+   ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
+@@ -348,13 +377,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) {
+   Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
\r
+   Status = Dhcp6AppendIaOption (\r
+-             Dhcp6AppendIaOptionTest::Packet,\r
+-             &Cursor,\r
+-             Ia,\r
+-             0,\r
+-             0,\r
+-             Dhcp6OptIata\r
+-             );\r
++                                Dhcp6AppendIaOptionTest::Packet,\r
++                                &Cursor,\r
++                                Ia,\r
++                                0,\r
++                                0,\r
++                                Dhcp6OptIata\r
++                                );\r
\r
+   // verify that we error out because the packet is too small for the option header\r
+   ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);\r
+@@ -406,13 +435,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) {
+   Ia->Descriptor.IaId = 0x12345678;\r
\r
+   Status = Dhcp6AppendIaOption (\r
+-             Dhcp6AppendIaOptionTest::Packet,\r
+-             &Cursor,\r
+-             Ia,\r
+-             0x12345678,\r
+-             0x12345678,\r
+-             Dhcp6OptIana\r
+-             );\r
++                                Dhcp6AppendIaOptionTest::Packet,\r
++                                &Cursor,\r
++                                Ia,\r
++                                0x12345678,\r
++                                0x12345678,\r
++                                Dhcp6OptIana\r
++                                );\r
\r
+   // verify that the pointer to cursor moved by the expected amount\r
+   ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);\r
+@@ -450,7 +479,7 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
+   //\r
+   ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;\r
\r
+-  Cursor      = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
++  Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;\r
\r
+   Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
+   OriginalLength = Packet->Length;\r
+@@ -459,13 +488,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
+   Ia->Descriptor.IaId = 0x12345678;\r
\r
+   Status = Dhcp6AppendIaOption (\r
+-             Dhcp6AppendIaOptionTest::Packet,\r
+-             &Cursor,\r
+-             Ia,\r
+-             0,\r
+-             0,\r
+-             Dhcp6OptIata\r
+-             );\r
++                                Dhcp6AppendIaOptionTest::Packet,\r
++                                &Cursor,\r
++                                Ia,\r
++                                0,\r
++                                0,\r
++                                Dhcp6OptIata\r
++                                );\r
\r
+   // verify that the pointer to cursor moved by the expected amount\r
+   ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);\r
+@@ -476,3 +505,335 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
+   // verify that the status is EFI_SUCCESS\r
+   ASSERT_EQ (Status, EFI_SUCCESS);\r
+ }\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++// Dhcp6SeekInnerOptionSafe Tests\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++// Define a fixture for your tests if needed\r
++class Dhcp6SeekInnerOptionSafeTest : public ::testing::Test {\r
++protected:\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++  // Initialize any resources or variables\r
++}\r
++\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++  // Clean up any resources or variables\r
++}\r
++};\r
++\r
++// Test Description:\r
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IANA option is found.\r
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAValidOptionExpectSuccess) {\r
++  EFI_STATUS           Result;\r
++  UINT8                Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 };\r
++  UINT32               OptionLength                                              = sizeof (Option);\r
++  DHCPv6_OPTION_IA_NA  *OptionPtr                                                = (DHCPv6_OPTION_IA_NA *)Option;\r
++  UINT32               SearchPattern                                             = SEARCH_PATTERN;\r
++\r
++  UINTN   SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  UINT8   *InnerOptionPtr     = NULL;\r
++  UINT16  InnerOptionLength   = 0;\r
++\r
++  OptionPtr->Header.Code = Dhcp6OptIana;\r
++  OptionPtr->Header.Len  = HTONS (4 + 12); // Valid length has to be more than 12\r
++  OptionPtr->Header.IAID = 0x12345678;\r
++  OptionPtr->T1          = 0x11111111;\r
++  OptionPtr->T2          = 0x22222222;\r
++  CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);\r
++\r
++  Result = Dhcp6SeekInnerOptionSafe (\r
++                                     Dhcp6OptIana,\r
++                                     Option,\r
++                                     OptionLength,\r
++                                     &InnerOptionPtr,\r
++                                     &InnerOptionLength\r
++                                     );\r
++  ASSERT_EQ (Result, EFI_SUCCESS);\r
++  ASSERT_EQ (InnerOptionLength, 4);\r
++  ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);\r
++}\r
++\r
++// Test Description:\r
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_DEIVCE_ERROR when the IANA option size is invalid.\r
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAInvalidSizeExpectFail) {\r
++  // Lets add an inner option of bytes we expect to find\r
++  EFI_STATUS           Status;\r
++  UINT8                Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 };\r
++  UINT32               OptionLength                                              = sizeof (Option);\r
++  DHCPv6_OPTION_IA_NA  *OptionPtr                                                = (DHCPv6_OPTION_IA_NA *)Option;\r
++  UINT32               SearchPattern                                             = SEARCH_PATTERN;\r
++\r
++  UINTN   SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  UINT8   *InnerOptionPtr     = NULL;\r
++  UINT16  InnerOptionLength   = 0;\r
++\r
++  OptionPtr->Header.Code = Dhcp6OptIana;\r
++  OptionPtr->Header.Len  = HTONS (4); // Set the length to lower than expected (12)\r
++  OptionPtr->Header.IAID = 0x12345678;\r
++  OptionPtr->T1          = 0x11111111;\r
++  OptionPtr->T2          = 0x22222222;\r
++  CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);\r
++\r
++  // Set the InnerOptionLength to be less than the size of the option\r
++  Status = Dhcp6SeekInnerOptionSafe (\r
++                                     Dhcp6OptIana,\r
++                                     Option,\r
++                                     OptionLength,\r
++                                     &InnerOptionPtr,\r
++                                     &InnerOptionLength\r
++                                     );\r
++  ASSERT_EQ (Status, EFI_DEVICE_ERROR);\r
++\r
++  // Now set the OptionLength to be less than the size of the option\r
++  OptionLength = sizeof (DHCPv6_OPTION_IA_NA) - 1;\r
++  Status       = Dhcp6SeekInnerOptionSafe (\r
++                                           Dhcp6OptIana,\r
++                                           Option,\r
++                                           OptionLength,\r
++                                           &InnerOptionPtr,\r
++                                           &InnerOptionLength\r
++                                           );\r
++  ASSERT_EQ (Status, EFI_DEVICE_ERROR);\r
++}\r
++\r
++// Test Description:\r
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option is found\r
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAValidOptionExpectSuccess) {\r
++  // Lets add an inner option of bytes we expect to find\r
++  EFI_STATUS           Status;\r
++  UINT8                Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };\r
++  UINT32               OptionLength                                              = sizeof (Option);\r
++  DHCPv6_OPTION_IA_TA  *OptionPtr                                                = (DHCPv6_OPTION_IA_TA *)Option;\r
++  UINT32               SearchPattern                                             = SEARCH_PATTERN;\r
++\r
++  UINTN   SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  UINT8   *InnerOptionPtr     = NULL;\r
++  UINT16  InnerOptionLength   = 0;\r
++\r
++  OptionPtr->Header.Code = Dhcp6OptIata;\r
++  OptionPtr->Header.Len  = HTONS (4 + 4); // Valid length has to be more than 4\r
++  OptionPtr->Header.IAID = 0x12345678;\r
++  CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);\r
++\r
++  Status = Dhcp6SeekInnerOptionSafe (\r
++                                     Dhcp6OptIata,\r
++                                     Option,\r
++                                     OptionLength,\r
++                                     &InnerOptionPtr,\r
++                                     &InnerOptionLength\r
++                                     );\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++  ASSERT_EQ (InnerOptionLength, 4);\r
++  ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);\r
++}\r
++\r
++// Test Description:\r
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid.\r
++TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAInvalidSizeExpectFail) {\r
++  // Lets add an inner option of bytes we expect to find\r
++  EFI_STATUS           Status;\r
++  UINT8                Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };\r
++  UINT32               OptionLength                                              = sizeof (Option);\r
++  DHCPv6_OPTION_IA_TA  *OptionPtr                                                = (DHCPv6_OPTION_IA_TA *)Option;\r
++  UINT32               SearchPattern                                             = SEARCH_PATTERN;\r
++\r
++  UINTN   SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  UINT8   *InnerOptionPtr     = NULL;\r
++  UINT16  InnerOptionLength   = 0;\r
++\r
++  OptionPtr->Header.Code = Dhcp6OptIata;\r
++  OptionPtr->Header.Len  = HTONS (2); // Set the length to lower than expected (4)\r
++  OptionPtr->Header.IAID = 0x12345678;\r
++  CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);\r
++\r
++  Status = Dhcp6SeekInnerOptionSafe (\r
++                                     Dhcp6OptIata,\r
++                                     Option,\r
++                                     OptionLength,\r
++                                     &InnerOptionPtr,\r
++                                     &InnerOptionLength\r
++                                     );\r
++  ASSERT_EQ (Status, EFI_DEVICE_ERROR);\r
++\r
++  // Now lets try modifying the OptionLength to be less than the size of the option\r
++  OptionLength = sizeof (DHCPv6_OPTION_IA_TA) - 1;\r
++  Status       = Dhcp6SeekInnerOptionSafe (\r
++                                           Dhcp6OptIata,\r
++                                           Option,\r
++                                           OptionLength,\r
++                                           &InnerOptionPtr,\r
++                                           &InnerOptionLength\r
++                                           );\r
++  ASSERT_EQ (Status, EFI_DEVICE_ERROR);\r
++}\r
++\r
++// Test Description:\r
++// This test verifies that any other Option Type fails\r
++TEST_F (Dhcp6SeekInnerOptionSafeTest, InvalidOption) {\r
++  // Lets add an inner option of bytes we expect to find\r
++  EFI_STATUS           Result;\r
++  UINT8                Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };\r
++  UINT32               OptionLength                                              = sizeof (Option);\r
++  DHCPv6_OPTION_IA_TA  *OptionPtr                                                = (DHCPv6_OPTION_IA_TA *)Option;\r
++  UINT32               SearchPattern                                             = SEARCH_PATTERN;\r
++\r
++  UINTN   SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  UINT8   *InnerOptionPtr     = NULL;\r
++  UINT16  InnerOptionLength   = 0;\r
++\r
++  OptionPtr->Header.Code = 0xC0DE;\r
++  OptionPtr->Header.Len  = HTONS (2); // Set the length to lower than expected (4)\r
++  OptionPtr->Header.IAID = 0x12345678;\r
++  CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);\r
++\r
++  Result = Dhcp6SeekInnerOptionSafe (0xC0DE, Option, OptionLength, &InnerOptionPtr, &InnerOptionLength);\r
++  ASSERT_EQ (Result, EFI_DEVICE_ERROR);\r
++}\r
++\r
++////////////////////////////////////////////////////////////////////////\r
++// Dhcp6SeekStsOption Tests\r
++////////////////////////////////////////////////////////////////////////\r
++\r
++#define PACKET_SIZE  (1500)\r
++\r
++class Dhcp6SeekStsOptionTest : public ::testing::Test {\r
++public:\r
++DHCP6_INSTANCE Instance      = { 0 };\r
++EFI_DHCP6_PACKET *Packet     = NULL;\r
++EFI_DHCP6_CONFIG_DATA Config = { 0 };\r
++\r
++protected:\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++  // Allocate a packet\r
++  Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);\r
++  ASSERT_NE (Packet, nullptr);\r
++\r
++  // Initialize the packet\r
++  Packet->Size = PACKET_SIZE;\r
++\r
++  Instance.Config = &Config;\r
++}\r
++\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++  // Clean up any resources or variables\r
++  FreePool (Packet);\r
++}\r
++};\r
++\r
++// Test Description:\r
++// This test verifies that Dhcp6SeekStsOption returns EFI_DEVICE_ERROR when the option is invalid\r
++// This verifies that the calling function is working as expected\r
++TEST_F (Dhcp6SeekStsOptionTest, SeekIATAOptionExpectFail) {\r
++  EFI_STATUS    Status;\r
++  UINT8         *Option             = NULL;\r
++  UINT32        SearchPattern       = SEARCH_PATTERN;\r
++  UINT16        SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  UINT16        *Len                = NULL;\r
++  EFI_DHCP6_IA  Ia                  = { 0 };\r
++\r
++  Ia.Descriptor.Type                = DHCPV6_OPTION_IA_TA;\r
++  Ia.IaAddressCount                 = 1;\r
++  Ia.IaAddress[0].PreferredLifetime = 0xDEADBEEF;\r
++  Ia.IaAddress[0].ValidLifetime     = 0xDEADAAAA;\r
++  Ia.IaAddress[0].IpAddress         = mAllDhcpRelayAndServersAddress;\r
++\r
++  Packet->Length = sizeof (EFI_DHCP6_HEADER);\r
++\r
++  Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;\r
++\r
++  // Let's append the option to the packet\r
++  Status = Dhcp6AppendOption (\r
++             Dhcp6SeekStsOptionTest::Packet,\r
++             &Option,\r
++             Dhcp6OptStatusCode,\r
++             SearchPatternLength,\r
++             (UINT8 *)&SearchPattern\r
++             );\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++\r
++  // Inner option length - this will be overwritten later\r
++  Len = (UINT16 *)(Option + 2);\r
++\r
++  // Fill in the inner IA option\r
++  Status = Dhcp6AppendIaOption (\r
++             Dhcp6SeekStsOptionTest::Packet,\r
++             &Option,\r
++             &Ia,\r
++             0x12345678,\r
++             0x11111111,\r
++             0x22222222\r
++             );\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++\r
++  // overwrite the len of inner Ia option\r
++  *Len = HTONS (3);\r
++\r
++  Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_TA;\r
++\r
++  Option = NULL;\r
++  Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);\r
++\r
++  ASSERT_EQ (Status, EFI_DEVICE_ERROR);\r
++}\r
++\r
++// Test Description:\r
++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid.\r
++TEST_F (Dhcp6SeekStsOptionTest, SeekIANAOptionExpectSuccess) {\r
++  EFI_STATUS    Status              = EFI_NOT_FOUND;\r
++  UINT8         *Option             = NULL;\r
++  UINT32        SearchPattern       = SEARCH_PATTERN;\r
++  UINT16        SearchPatternLength = SEARCH_PATTERN_LEN;\r
++  EFI_DHCP6_IA  Ia                  = { 0 };\r
++\r
++  Ia.Descriptor.Type                = DHCPV6_OPTION_IA_NA;\r
++  Ia.IaAddressCount                 = 1;\r
++  Ia.IaAddress[0].PreferredLifetime = 0x11111111;\r
++  Ia.IaAddress[0].ValidLifetime     = 0x22222222;\r
++  Ia.IaAddress[0].IpAddress         = mAllDhcpRelayAndServersAddress;\r
++  Packet->Length                    = sizeof (EFI_DHCP6_HEADER);\r
++\r
++  Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;\r
++\r
++  Status = Dhcp6AppendOption (\r
++             Dhcp6SeekStsOptionTest::Packet,\r
++             &Option,\r
++             Dhcp6OptStatusCode,\r
++             SearchPatternLength,\r
++             (UINT8 *)&SearchPattern\r
++             );\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++\r
++  Status = Dhcp6AppendIaOption (\r
++             Dhcp6SeekStsOptionTest::Packet,\r
++             &Option,\r
++             &Ia,\r
++             0x12345678,\r
++             0x11111111,\r
++             0x22222222\r
++             );\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++\r
++  Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_NA;\r
++\r
++  Option = NULL;\r
++  Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);\r
++\r
++  ASSERT_EQ (Status, EFI_SUCCESS);\r
++}\r
+diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
+new file mode 100644
+index 0000000000..c5e38daf9c
+--- /dev/null
++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
+@@ -0,0 +1,58 @@
++/** @file
++  Acts as header for private functions under test in Dhcp6Io.c
++
++  Copyright (c) Microsoft Corporation
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++
++#ifndef DHCP6_IO_GOOGLE_TEST_H
++#define DHCP6_IO_GOOGLE_TEST_H
++
++////////////////////////////////////////////////////////////////////////////////
++// These are the functions that are being unit tested
++////////////////////////////////////////////////////////////////////////////////
++
++#include <Uefi.h>
++
++/**
++  Seeks the Inner Options from a DHCP6 Option
++
++  @param[in]  IaType          The type of the IA option.
++  @param[in]  Option          The pointer to the DHCP6 Option.
++  @param[in]  OptionLen       The length of the DHCP6 Option.
++  @param[out] IaInnerOpt      The pointer to the IA inner option.
++  @param[out] IaInnerLen      The length of the IA inner option.
++
++  @retval EFI_SUCCESS         Seek the inner option successfully.
++  @retval EFI_DEVICE_ERROR    The OptionLen is invalid.
++*/
++EFI_STATUS
++Dhcp6SeekInnerOptionSafe (
++  UINT16  IaType,
++  UINT8   *Option,
++  UINT32  OptionLen,
++  UINT8   **IaInnerOpt,
++  UINT16  *IaInnerLen
++  );
++
++/**
++  Seek StatusCode Option in package. A Status Code option may appear in the
++  options field of a DHCP message and/or in the options field of another option.
++  See details in section 22.13, RFC3315.
++
++  @param[in]       Instance        The pointer to the Dhcp6 instance.
++  @param[in]       Packet          The pointer to reply messages.
++  @param[out]      Option          The pointer to status code option.
++
++  @retval EFI_SUCCESS              Seek status code option successfully.
++  @retval EFI_DEVICE_ERROR         An unexpected error.
++
++**/
++EFI_STATUS
++Dhcp6SeekStsOption (
++  IN     DHCP6_INSTANCE    *Instance,
++  IN     EFI_DHCP6_PACKET  *Packet,
++  OUT    UINT8             **Option
++  );
++
++#endif // DHCP6_IO_GOOGLE_TEST_H
+diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+index 5befdf7688..f6459b124f 100644
+--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+@@ -1,102 +1,102 @@
+-## @file\r
+-# NetworkPkgHostTest DSC file used to build host-based unit tests.\r
+-#\r
+-# Copyright (c) Microsoft Corporation.<BR>\r
+-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-#\r
+-##\r
+-[Defines]\r
+-  PLATFORM_NAME           = NetworkPkgHostTest\r
+-  PLATFORM_GUID           = 3b68324e-fc07-4d49-9520-9347ede65879\r
+-  PLATFORM_VERSION        = 0.1\r
+-  DSC_SPECIFICATION       = 0x00010005\r
+-  OUTPUT_DIRECTORY        = Build/NetworkPkg/HostTest\r
+-  SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64\r
+-  BUILD_TARGETS           = NOOPT\r
+-  SKUID_IDENTIFIER        = DEFAULT\r
+-  \r
+-!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc\r
+-[Packages]\r
+-  MdePkg/MdePkg.dec\r
+-  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
+-\r
+-[Components]\r
+-  #\r
+-  # Build HOST_APPLICATION that tests NetworkPkg\r
+-  #\r
+-  NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf\r
+-\r
+-# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.\r
+-[LibraryClasses]\r
+-  NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf\r
+-  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
+-  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
+-  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
+-  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+-  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
+-  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+-  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+-  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
+-  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
+-  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
+-  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
+-  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
+-  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
+-  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf\r
+-  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf\r
+-  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
+-  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
+-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+-  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
+-  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
+-  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf\r
+-  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf\r
+-  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf\r
+-!ifdef CONTINUOUS_INTEGRATION\r
+-  BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf\r
+-  TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf\r
+-!else\r
+-  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
+-  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
+-  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf\r
+-!endif\r
+-  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf\r
+-  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf\r
+-  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf\r
+-  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf\r
+-  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf\r
+-\r
+-!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022\r
+-[LibraryClasses.X64]\r
+-  # Provide StackCookie support lib so that we can link to /GS exports for VS builds\r
+-  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf\r
+-  NULL|MdePkg/Library/BaseBinSecurityLibRng/BaseBinSecurityLibRng.inf\r
+-!endif\r
+-\r
+-[LibraryClasses.common.UEFI_DRIVER]\r
+-  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+-  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf\r
+-  DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf\r
+-[LibraryClasses.common.UEFI_APPLICATION]\r
+-  DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf\r
+-  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf\r
+-[LibraryClasses.ARM, LibraryClasses.AARCH64]\r
+-  #\r
+-  # It is not possible to prevent ARM compiler calls to generic intrinsic functions.\r
+-  # This library provides the instrinsic functions generated by a given compiler.\r
+-  # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.\r
+-  #\r
+-  # MU_CHANGE Start\r
+-!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019\r
+-  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf\r
+-!endif\r
+-  # MU_CHANGE End\r
+-  NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf\r
+-[LibraryClasses.ARM]\r
+-  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf\r
+-[LibraryClasses.RISCV64]\r
+-  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf\r
+-  \r
+-[PcdsFixedAtBuild]\r
+-  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2\r
+-  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
+\ No newline at end of file
++## @file
++# NetworkPkgHostTest DSC file used to build host-based unit tests.
++#
++# Copyright (c) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++#
++##
++[Defines]
++  PLATFORM_NAME           = NetworkPkgHostTest
++  PLATFORM_GUID           = 3b68324e-fc07-4d49-9520-9347ede65879
++  PLATFORM_VERSION        = 0.1
++  DSC_SPECIFICATION       = 0x00010005
++  OUTPUT_DIRECTORY        = Build/NetworkPkg/HostTest
++  SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
++  BUILD_TARGETS           = NOOPT
++  SKUID_IDENTIFIER        = DEFAULT
++  
++!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
++[Packages]
++  MdePkg/MdePkg.dec
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++
++[Components]
++  #
++  # Build HOST_APPLICATION that tests NetworkPkg
++  #
++  NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
++
++# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
++[LibraryClasses]
++  NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
++  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
++  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
++  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
++  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
++  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
++  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
++  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
++  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
++  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
++  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
++  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
++  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
++  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
++  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
++  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
++  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
++  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
++  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
++  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
++  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
++  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
++  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
++  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
++!ifdef CONTINUOUS_INTEGRATION
++  BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
++  TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf
++!else
++  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
++  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
++  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
++!endif
++  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
++  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
++  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
++  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
++  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
++
++!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022
++[LibraryClasses.X64]
++  # Provide StackCookie support lib so that we can link to /GS exports for VS builds
++  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
++  NULL|MdePkg/Library/BaseBinSecurityLibRng/BaseBinSecurityLibRng.inf
++!endif
++
++[LibraryClasses.common.UEFI_DRIVER]
++  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
++  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
++  DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
++[LibraryClasses.common.UEFI_APPLICATION]
++  DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
++  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
++[LibraryClasses.ARM, LibraryClasses.AARCH64]
++  #
++  # It is not possible to prevent ARM compiler calls to generic intrinsic functions.
++  # This library provides the instrinsic functions generated by a given compiler.
++  # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
++  #
++  # MU_CHANGE Start
++!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
++  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
++!endif
++  # MU_CHANGE End
++  NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
++[LibraryClasses.ARM]
++  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
++[LibraryClasses.RISCV64]
++  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
++  
++[PcdsFixedAtBuild]
++  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
+-- 
+2.41.0
+
+
+From d74c1be05f439ab3b94ac50f8b46cece775c8ee7 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 15 Dec 2023 13:32:28 -0800
+Subject: [PATCH 05/12] SECURITY PATCH TCBZ4536 - CVE-2023-45231 - Patch
+
+---
+ NetworkPkg/Ip6Dxe/Ip6Option.c | 112 ++++++++++++++++++----------------
+ 1 file changed, 60 insertions(+), 52 deletions(-)
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
+index 199eea124d..bc74d52a6c 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
+@@ -76,27 +76,27 @@ Ip6IsOptionValid (
+           case Ip6OptionParameterProblem:\r
+             Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);\r
+             Ip6SendIcmpError (\r
+-              IpSb,\r
+-              Packet,\r
+-              NULL,\r
+-              &Packet->Ip.Ip6->SourceAddress,\r
+-              ICMP_V6_PARAMETER_PROBLEM,\r
+-              2,\r
+-              &Pointer\r
+-              );\r
++                              IpSb,\r
++                              Packet,\r
++                              NULL,\r
++                              &Packet->Ip.Ip6->SourceAddress,\r
++                              ICMP_V6_PARAMETER_PROBLEM,\r
++                              2,\r
++                              &Pointer\r
++                              );\r
+             return FALSE;\r
+           case Ip6OptionMask:\r
+             if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {\r
+               Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);\r
+               Ip6SendIcmpError (\r
+-                IpSb,\r
+-                Packet,\r
+-                NULL,\r
+-                &Packet->Ip.Ip6->SourceAddress,\r
+-                ICMP_V6_PARAMETER_PROBLEM,\r
+-                2,\r
+-                &Pointer\r
+-                );\r
++                                IpSb,\r
++                                Packet,\r
++                                NULL,\r
++                                &Packet->Ip.Ip6->SourceAddress,\r
++                                ICMP_V6_PARAMETER_PROBLEM,\r
++                                2,\r
++                                &Pointer\r
++                                );\r
+             }\r
\r
+             return FALSE;\r
+@@ -137,6 +137,14 @@ Ip6IsNDOptionValid (
+     return FALSE;\r
+   }\r
\r
++  //\r
++  // Cannot process truncated options.\r
++  // Cannot process options with a length of 0 as there is no Type field.\r
++  //\r
++  if (OptionLen < sizeof (IP6_OPTION_HEADER)) {\r
++    return FALSE;\r
++  }\r
++\r
+   Offset = 0;\r
\r
+   //\r
+@@ -358,14 +366,14 @@ Ip6IsExtsValid (
+               !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))\r
+           {\r
+             Ip6SendIcmpError (\r
+-              IpSb,\r
+-              Packet,\r
+-              NULL,\r
+-              &Packet->Ip.Ip6->SourceAddress,\r
+-              ICMP_V6_PARAMETER_PROBLEM,\r
+-              1,\r
+-              &Pointer\r
+-              );\r
++                              IpSb,\r
++                              Packet,\r
++                              NULL,\r
++                              &Packet->Ip.Ip6->SourceAddress,\r
++                              ICMP_V6_PARAMETER_PROBLEM,\r
++                              1,\r
++                              &Pointer\r
++                              );\r
+           }\r
\r
+           return FALSE;\r
+@@ -438,14 +446,14 @@ Ip6IsExtsValid (
+               !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))\r
+           {\r
+             Ip6SendIcmpError (\r
+-              IpSb,\r
+-              Packet,\r
+-              NULL,\r
+-              &Packet->Ip.Ip6->SourceAddress,\r
+-              ICMP_V6_PARAMETER_PROBLEM,\r
+-              0,\r
+-              &Pointer\r
+-              );\r
++                              IpSb,\r
++                              Packet,\r
++                              NULL,\r
++                              &Packet->Ip.Ip6->SourceAddress,\r
++                              ICMP_V6_PARAMETER_PROBLEM,\r
++                              0,\r
++                              &Pointer\r
++                              );\r
+           }\r
\r
+           return FALSE;\r
+@@ -484,14 +492,14 @@ Ip6IsExtsValid (
+           {\r
+             Pointer = sizeof (UINT32);\r
+             Ip6SendIcmpError (\r
+-              IpSb,\r
+-              Packet,\r
+-              NULL,\r
+-              &Packet->Ip.Ip6->SourceAddress,\r
+-              ICMP_V6_PARAMETER_PROBLEM,\r
+-              0,\r
+-              &Pointer\r
+-              );\r
++                              IpSb,\r
++                              Packet,\r
++                              NULL,\r
++                              &Packet->Ip.Ip6->SourceAddress,\r
++                              ICMP_V6_PARAMETER_PROBLEM,\r
++                              0,\r
++                              &Pointer\r
++                              );\r
+             return FALSE;\r
+           }\r
+         }\r
+@@ -560,14 +568,14 @@ Ip6IsExtsValid (
+             !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))\r
+         {\r
+           Ip6SendIcmpError (\r
+-            IpSb,\r
+-            Packet,\r
+-            NULL,\r
+-            &Packet->Ip.Ip6->SourceAddress,\r
+-            ICMP_V6_PARAMETER_PROBLEM,\r
+-            1,\r
+-            &Pointer\r
+-            );\r
++                            IpSb,\r
++                            Packet,\r
++                            NULL,\r
++                            &Packet->Ip.Ip6->SourceAddress,\r
++                            ICMP_V6_PARAMETER_PROBLEM,\r
++                            1,\r
++                            &Pointer\r
++                            );\r
+         }\r
\r
+         return FALSE;\r
+@@ -774,10 +782,10 @@ Ip6FillFragmentHeader (
+     // Append the part2 (fragmentable part) of Extension headers\r
+     //\r
+     CopyMem (\r
+-      Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),\r
+-      ExtHdrs + Part1Len,\r
+-      ExtHdrsLen - Part1Len\r
+-      );\r
++             Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),\r
++             ExtHdrs + Part1Len,\r
++             ExtHdrsLen - Part1Len\r
++             );\r
+   }\r
\r
+   *UpdatedExtHdrs = Buffer;\r
+-- 
+2.41.0
+
+
+From 2f237a59ec4ea3df4b1614566ac29c90fb106669 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Fri, 15 Dec 2023 13:55:30 -0800
+Subject: [PATCH 06/12] SECURITY PATCH TCBZ4536 - CVE-2023-45231 - Host Based
+ Unit Test
+
+---
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp    |  27 ++++
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf    |  42 ++++++
+ .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++
+ NetworkPkg/Test/NetworkPkgHostTest.dsc        |   1 +
+ 4 files changed, 199 insertions(+)
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..9dd5577249
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+@@ -0,0 +1,27 @@
++/** @file
++  Acts as the main entry point for the tests for the Ip6Dxe module.
++
++  Copyright (c) Microsoft Corporation
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++////////////////////////////////////////////////////////////////////////////////
++// Add test files here
++// Google Test will only pick up the tests from the files that are included
++// here.
++////////////////////////////////////////////////////////////////////////////////
++#include "Ip6OptionGoogleTest.cpp"
++
++////////////////////////////////////////////////////////////////////////////////
++// Run the tests
++////////////////////////////////////////////////////////////////////////////////
++int
++main (
++  int   argc,
++  char  *argv[]
++  )
++{
++  testing::InitGoogleTest (&argc, argv);
++  return RUN_ALL_TESTS ();
++}
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+new file mode 100644
+index 0000000000..b85584b796
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+@@ -0,0 +1,42 @@
++## @file
++# Unit test suite for the Ip6Dxe using Google Test
++#
++# Copyright (c) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++[Defines]
++  INF_VERSION         = 0x00010017
++  BASE_NAME           = Ip6DxeUnitTest
++  FILE_GUID           = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A
++  VERSION_STRING      = 1.0
++  MODULE_TYPE         = HOST_APPLICATION
++#
++# The following information is for reference only and not required by the build tools.
++#
++#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
++#
++[Sources]
++  Ip6DxeGoogleTest.cpp
++  Ip6OptionGoogleTest.cpp
++  ../Ip6Option.c
++
++[Packages]
++  MdePkg/MdePkg.dec
++  MdeModulePkg/MdeModulePkg.dec
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++  NetworkPkg/NetworkPkg.dec
++
++[LibraryClasses]
++  GoogleTestLib
++  DebugLib
++  NetLib
++  PcdLib
++
++[Protocols]
++  gEfiDhcp6ServiceBindingProtocolGuid
++
++[Pcd]
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
++
++[Guids]
++  gZeroGuid  
+\ No newline at end of file
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+new file mode 100644
+index 0000000000..c4bcfacb92
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+@@ -0,0 +1,129 @@
++/** @file
++  Tests for Ip6Option.c.
++
++  Copyright (c) Microsoft Corporation
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++extern "C" {
++  #include <Uefi.h>
++  #include <Library/BaseLib.h>
++  #include <Library/DebugLib.h>
++  #include "../Ip6Impl.h"
++  #include "../Ip6Option.h"
++}
++
++/////////////////////////////////////////////////////////////////////////
++// Defines
++///////////////////////////////////////////////////////////////////////
++
++#define IP6_PREFIX_INFO_OPTION_DATA_LEN    32
++#define OPTION_HEADER_IP6_PREFIX_DATA_LEN  (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN)
++
++////////////////////////////////////////////////////////////////////////
++// Symbol Definitions
++// These functions are not directly under test - but required to compile
++////////////////////////////////////////////////////////////////////////
++UINT32  mIp6Id;
++
++EFI_STATUS
++Ip6SendIcmpError (
++  IN IP6_SERVICE       *IpSb,
++  IN NET_BUF           *Packet,
++  IN EFI_IPv6_ADDRESS  *SourceAddress       OPTIONAL,
++  IN EFI_IPv6_ADDRESS  *DestinationAddress,
++  IN UINT8             Type,
++  IN UINT8             Code,
++  IN UINT32            *Pointer             OPTIONAL
++  )
++{
++  // ..
++  return EFI_SUCCESS;
++}
++
++////////////////////////////////////////////////////////////////////////
++// Ip6OptionValidation Tests
++////////////////////////////////////////////////////////////////////////
++
++// Define a fixture for your tests if needed
++class Ip6OptionValidationTest : public ::testing::Test {
++protected:
++  // Add any setup code if needed
++  virtual void
++  SetUp (
++    )
++  {
++    // Initialize any resources or variables
++  }
++
++  // Add any cleanup code if needed
++  virtual void
++  TearDown (
++    )
++  {
++    // Clean up any resources or variables
++  }
++};
++
++// Test Description:
++// Null option should return false
++TEST_F (Ip6OptionValidationTest, NullOptionShouldReturnFalse) {
++  UINT8   *option   = nullptr;
++  UINT16  optionLen = 10; // Provide a suitable length
++
++  EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++// Test Description:
++// Truncated option should return false
++TEST_F (Ip6OptionValidationTest, TruncatedOptionShouldReturnFalse) {
++  UINT8   option[]  = { 0x01 }; // Provide a truncated option
++  UINT16  optionLen = 1;
++
++  EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++// Test Description:
++// Ip6OptionPrefixInfo Option with zero length should return false
++TEST_F (Ip6OptionValidationTest, OptionWithZeroLengthShouldReturnFalse) {
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPrefixInfo;
++  optionHeader.Length = 0;
++  UINT8  option[sizeof (IP6_OPTION_HEADER)];
++
++  CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
++  UINT16  optionLen = sizeof (IP6_OPTION_HEADER);
++
++  EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++// Test Description:
++// Ip6OptionPrefixInfo Option with valid length should return true
++TEST_F (Ip6OptionValidationTest, ValidPrefixInfoOptionShouldReturnTrue) {
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPrefixInfo;
++  optionHeader.Length = 4; // Length 4 * 8 = 32
++  UINT8  option[OPTION_HEADER_IP6_PREFIX_DATA_LEN];
++
++  CopyMem (option, &optionHeader, OPTION_HEADER_IP6_PREFIX_DATA_LEN);
++
++  EXPECT_FALSE (Ip6IsNDOptionValid (option, OPTION_HEADER_IP6_PREFIX_DATA_LEN));
++}
++
++// Test Description:
++// Ip6OptionPrefixInfo Option with invalid length should return false
++TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) {
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPrefixInfo;
++  optionHeader.Length = 3; // Length 3 * 8 = 24 (Invalid)
++  UINT8  option[sizeof (IP6_OPTION_HEADER)];
++
++  CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
++  UINT16  optionLen = sizeof (IP6_OPTION_HEADER);
++
++  EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
+\ No newline at end of file
+diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+index f6459b124f..8ed3585c06 100644
+--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+@@ -25,6 +25,7 @@
+   # Build HOST_APPLICATION that tests NetworkPkg
+   #
+   NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
++  NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+ # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
+ [LibraryClasses]
+-- 
+2.41.0
+
+
+From 7ec488242f6c634a6e08fda25e4196ab24bf2d42 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Mon, 18 Dec 2023 10:37:40 -0800
+Subject: [PATCH 07/12] SECURITY PATCH TCBZ4537 / TCBZ4538 - CVE-2023-45232 /
+ CVE-2023-45233 - Patch
+
+---
+ NetworkPkg/Ip6Dxe/Ip6Option.c | 81 ++++++++++++++++++++++++++-----
+ NetworkPkg/Ip6Dxe/Ip6Option.h | 89 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 157 insertions(+), 13 deletions(-)
+
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
+index bc74d52a6c..9ca4d6ae5d 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
+@@ -9,6 +9,7 @@
\r
+ #include "Ip6Impl.h"\r
\r
++\r
+ /**\r
+   Validate the IP6 option format for both the packets we received\r
+   and that we will transmit. It will compute the ICMPv6 error message fields\r
+@@ -17,7 +18,8 @@
+   @param[in]  IpSb              The IP6 service data.\r
+   @param[in]  Packet            The to be validated packet.\r
+   @param[in]  Option            The first byte of the option.\r
+-  @param[in]  OptionLen         The length of the whole option.\r
++  @param[in]  OptionLen         The length of all options, expressed in byte length of octets.\r
++                                Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255.\r
+   @param[in]  Pointer           Identifies the octet offset within\r
+                                 the invoking packet where the error was detected.\r
\r
+@@ -31,12 +33,33 @@ Ip6IsOptionValid (
+   IN IP6_SERVICE  *IpSb,\r
+   IN NET_BUF      *Packet,\r
+   IN UINT8        *Option,\r
+-  IN UINT8        OptionLen,\r
++  IN UINT16       OptionLen,\r
+   IN UINT32       Pointer\r
+   )\r
+ {\r
+-  UINT8  Offset;\r
+-  UINT8  OptionType;\r
++  UINT16  Offset;\r
++  UINT8   OptionType;\r
++  UINT8   OptDataLen;\r
++\r
++  if (Option == NULL) {\r
++    ASSERT (Option != NULL);\r
++    return FALSE;\r
++  }\r
++\r
++  if (OptionLen <= 0 || OptionLen > IP6_MAX_EXT_DATA_LENGTH) {\r
++    ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);\r
++    return FALSE;\r
++  }\r
++\r
++  if (Packet == NULL) {\r
++    ASSERT (Packet != NULL);\r
++    return FALSE;\r
++  }\r
++\r
++  if (IpSb == NULL) {\r
++    ASSERT (IpSb != NULL);\r
++    return FALSE;\r
++  }\r
\r
+   Offset = 0;\r
\r
+@@ -54,7 +77,8 @@ Ip6IsOptionValid (
+         //\r
+         // It is a PadN option\r
+         //\r
+-        Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);\r
++        OptDataLen = *(IP6_OFFSET_OF_OPT_LEN(Option + Offset));\r
++        Offset = IP6_NEXT_OPTION_OFFSET(Offset, OptDataLen);\r
+         break;\r
+       case Ip6OptionRouterAlert:\r
+         //\r
+@@ -69,7 +93,8 @@ Ip6IsOptionValid (
+         //\r
+         switch (OptionType & Ip6OptionMask) {\r
+           case Ip6OptionSkip:\r
+-            Offset = (UINT8)(Offset + *(Option + Offset + 1));\r
++            OptDataLen = *(IP6_OFFSET_OF_OPT_LEN(Option + Offset));\r
++            Offset = IP6_NEXT_OPTION_OFFSET(Offset, OptDataLen);\r
+             break;\r
+           case Ip6OptionDiscard:\r
+             return FALSE;\r
+@@ -308,7 +333,7 @@ Ip6IsExtsValid (
+   UINT32               Pointer;\r
+   UINT32               Offset;\r
+   UINT8                *Option;\r
+-  UINT8                OptionLen;\r
++  UINT16               OptionLen;\r
+   BOOLEAN              Flag;\r
+   UINT8                CountD;\r
+   UINT8                CountA;\r
+@@ -385,6 +410,36 @@ Ip6IsExtsValid (
+       // Fall through\r
+       //\r
+       case IP6_DESTINATION:\r
++        //\r
++        // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23\r
++        //\r
++        // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++        // |  Next Header  |  Hdr Ext Len  |                               |\r
++        // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +\r
++        // |                                                               |\r
++        // .                                                               .\r
++        // .                            Options                            .\r
++        // .                                                               .\r
++        // |                                                               |\r
++        // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++        //\r
++        //\r
++        //   Next Header    8-bit selector.  Identifies the type of header\r
++        //                  immediately following the Destination Options\r
++        //                  header.  Uses the same values as the IPv4\r
++        //                  Protocol field [RFC-1700 et seq.].\r
++        //\r
++        //   Hdr Ext Len    8-bit unsigned integer.  Length of the\r
++        //                  Destination Options header in 8-octet units, not\r
++        //                  including the first 8 octets.\r
++        //\r
++        //   Options        Variable-length field, of length such that the\r
++        //                  complete Destination Options header is an\r
++        //                  integer multiple of 8 octets long.  Contains one\r
++        //                  or  more TLV-encoded options, as described in\r
++        //                  section 4.2.\r
++        //\r
++\r
+         if (*NextHeader == IP6_DESTINATION) {\r
+           CountD++;\r
+         }\r
+@@ -397,8 +452,8 @@ Ip6IsExtsValid (
+         Pointer    = Offset;\r
\r
+         Offset++;\r
+-        Option    = ExtHdrs + Offset;\r
+-        OptionLen = (UINT8)((*Option + 1) * 8 - 2);\r
++        Option = ExtHdrs + Offset;\r
++        OptionLen = IP6_HDR_EXT_LEN(*Option) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;\r
+         Option++;\r
+         Offset++;\r
\r
+@@ -430,7 +485,7 @@ Ip6IsExtsValid (
+           //\r
+           // Ignore the routing header and proceed to process the next header.\r
+           //\r
+-          Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;\r
++          Offset = Offset + IP6_HDR_EXT_LEN(RoutingHead->HeaderLen);\r
\r
+           if (UnFragmentLen != NULL) {\r
+             *UnFragmentLen = Offset;\r
+@@ -441,7 +496,7 @@ Ip6IsExtsValid (
+           // to the packet's source address, pointing to the unrecognized routing\r
+           // type.\r
+           //\r
+-          Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);\r
++          Pointer = Offset + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN + sizeof (EFI_IP6_HEADER);\r
+           if ((IpSb != NULL) && (Packet != NULL) &&\r
+               !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))\r
+           {\r
+@@ -527,8 +582,8 @@ Ip6IsExtsValid (
+         //\r
+         // RFC2402, Payload length is specified in 32-bit words, minus "2".\r
+         //\r
+-        OptionLen = (UINT8)((*Option + 2) * 4);\r
+-        Offset    = Offset + OptionLen;\r
++        OptionLen = ((UINT16)(*Option + 2) * 4);\r
++        Offset = Offset + OptionLen;\r
+         break;\r
\r
+       case IP6_NO_NEXT_HEADER:\r
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
+index bd8e223c8a..1f9237b4e9 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Option.h
++++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
+@@ -12,6 +12,95 @@
\r
+ #define IP6_FRAGMENT_OFFSET_MASK  (~0x3)\r
\r
++//\r
++// Per RFC8200 Section 4.2\r
++//\r
++//   Two of the currently-defined extension headers -- the Hop-by-Hop\r
++//   Options header and the Destination Options header -- carry a variable\r
++//   number of type-length-value (TLV) encoded "options", of the following\r
++//   format:\r
++//\r
++//      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -\r
++//      |  Option Type  |  Opt Data Len |  Option Data\r
++//      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -\r
++//\r
++//      Option Type          8-bit identifier of the type of option.\r
++//\r
++//      Opt Data Len         8-bit unsigned integer.  Length of the Option\r
++//                           Data field of this option, in octets.\r
++//\r
++//      Option Data          Variable-length field.  Option-Type-specific\r
++//                           data.\r
++//\r
++#define IP6_SIZE_OF_OPT_TYPE                  (sizeof(UINT8))\r
++#define IP6_SIZE_OF_OPT_LEN                   (sizeof(UINT8))\r
++#define IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN  (IP6_SIZE_OF_OPT_TYPE + IP6_SIZE_OF_OPT_LEN)\r
++#define IP6_OFFSET_OF_OPT_LEN(a)  (a + IP6_SIZE_OF_OPT_TYPE)\r
++STATIC_ASSERT (\r
++               IP6_OFFSET_OF_OPT_LEN (0) == 1,\r
++               "The Length field should be 1 octet (8 bits) past the start of the option"\r
++               );\r
++\r
++#define IP6_NEXT_OPTION_OFFSET(offset, length)  (offset + IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN + length)\r
++STATIC_ASSERT (\r
++               IP6_NEXT_OPTION_OFFSET (0, 0) == 2,\r
++               "The next option is minimally the combined size of the option tag and length"\r
++               );\r
++\r
++//\r
++// For more information see RFC 8200, Section 4.3, 4.4, and 4.6\r
++//\r
++//  This example format is from section 4.6\r
++//  This does not apply to fragment headers\r
++//\r
++//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//    |  Next Header  |  Hdr Ext Len  |                               |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +\r
++//    |                                                               |\r
++//    .                                                               .\r
++//    .                  Header-Specific Data                         .\r
++//    .                                                               .\r
++//    |                                                               |\r
++//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
++//\r
++//      Next Header           8-bit selector.  Identifies the type of\r
++//                            header immediately following the extension\r
++//                            header.  Uses the same values as the IPv4\r
++//                            Protocol field [IANA-PN].\r
++//\r
++//      Hdr Ext Len           8-bit unsigned integer.  Length of the\r
++//                            Destination Options header in 8-octet units,\r
++//                            not including the first 8 octets.\r
++\r
++//\r
++// These defines apply to the following:\r
++//   1. Hop by Hop\r
++//   2. Routing\r
++//   3. Destination\r
++//\r
++#define IP6_SIZE_OF_EXT_NEXT_HDR  (sizeof(UINT8))\r
++#define IP6_SIZE_OF_HDR_EXT_LEN   (sizeof(UINT8))\r
++\r
++#define IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN  (IP6_SIZE_OF_EXT_NEXT_HDR + IP6_SIZE_OF_HDR_EXT_LEN)\r
++STATIC_ASSERT (\r
++               IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN == 2,\r
++               "The combined size of Next Header and Len is two 8 bit fields"\r
++               );\r
++\r
++//\r
++// The "+ 1" in this calculation is because of the "not including the first 8 octets"\r
++// part of the definition (meaning the value of 0 represents 64 bits)\r
++//\r
++#define IP6_HDR_EXT_LEN(a) (((UINT16)(UINT8)(a) + 1) * 8)\r
++\r
++// This is the maxmimum length permissible by a extension header\r
++// Length is UINT8 of 8 octets not including the first 8 octets\r
++#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN)\r
++STATIC_ASSERT (\r
++               IP6_MAX_EXT_DATA_LENGTH == 2046,\r
++               "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"\r
++               );\r
++\r
+ typedef struct _IP6_FRAGMENT_HEADER {\r
+   UINT8     NextHeader;\r
+   UINT8     Reserved;\r
+-- 
+2.41.0
+
+
+From d925ff1f00e769bcdbd04c1cb81560a8dec4e235 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Mon, 18 Dec 2023 10:49:41 -0800
+Subject: [PATCH 08/12] SECURITY PATCH TCBZ4537 / TCBZ4538 - CVE-2023-45232 /
+ CVE-2023-45233 - Host Based Unit Test
+
+---
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp    |   3 +-
+ .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf    |   5 +-
+ .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 344 +++++++++++++++++-
+ .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h   |  33 ++
+ NetworkPkg/Test/NetworkPkgHostTest.dsc        |   2 +-
+ 5 files changed, 376 insertions(+), 11 deletions(-)
+ create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
+
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+index 9dd5577249..5525da4231 100644
+--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
+@@ -1,6 +1,5 @@
+ /** @file
+-  Acts as the main entry point for the tests for the Ip6Dxe module.
+-
++  Acts as the main entry point for the tests for the Ip6Dxe driver.
+   Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+index b85584b796..9f4ce85157 100644
+--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+@@ -1,5 +1,5 @@
+ ## @file
+-# Unit test suite for the Ip6Dxe using Google Test
++# Unit test suite for the Ip6DxeGoogleTest using Google Test
+ #
+ # Copyright (c) Microsoft Corporation.<BR>
+ # SPDX-License-Identifier: BSD-2-Clause-Patent
+@@ -31,7 +31,6 @@
+   DebugLib
+   NetLib
+   PcdLib
+-
+ [Protocols]
+   gEfiDhcp6ServiceBindingProtocolGuid
+@@ -39,4 +38,4 @@
+   gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
+ [Guids]
+-  gZeroGuid  
+\ No newline at end of file
++  gZeroGuid  
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+index c4bcfacb92..640e96a17c 100644
+--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+@@ -1,5 +1,5 @@
+ /** @file
+-  Tests for Ip6Option.c.
++  Host based unit test for Ip6Option.c.
+   Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+@@ -12,18 +12,23 @@ extern "C" {
+   #include <Library/DebugLib.h>
+   #include "../Ip6Impl.h"
+   #include "../Ip6Option.h"
++  #include "Ip6OptionGoogleTest.h"
+ }
+ /////////////////////////////////////////////////////////////////////////
+ // Defines
+-///////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////
+ #define IP6_PREFIX_INFO_OPTION_DATA_LEN    32
+ #define OPTION_HEADER_IP6_PREFIX_DATA_LEN  (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN)
+-////////////////////////////////////////////////////////////////////////
+-// Symbol Definitions
+-// These functions are not directly under test - but required to compile
++///////////////////////////////////////////////////////////////////////
++// Symbol definitions
++//
++// These symbols / stub functions are required to be defined in order
++// to compile but are not under test. These can be converted to
++// Mock functions if required in the future.
++//
+ ////////////////////////////////////////////////////////////////////////
+ UINT32  mIp6Id;
+@@ -126,4 +131,333 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
+   UINT16  optionLen = sizeof (IP6_OPTION_HEADER);
+   EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
++}
++
++////////////////////////////////////////////////////////////////////////
++// Ip6IsOptionValid Tests
++////////////////////////////////////////////////////////////////////////
++
++// Define a fixture for your tests if needed
++class Ip6IsOptionValidTest : public ::testing::Test {
++protected:
++  // Add any setup code if needed
++  virtual void
++  SetUp (
++    )
++  {
++    // Initialize any resources or variables
++  }
++
++  // Add any cleanup code if needed
++  virtual void
++  TearDown (
++    )
++  {
++    // Clean up any resources or variables
++  }
++};
++
++// Test Description
++// Verify that a NULL option is Invalid
++TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  IP6_SERVICE  *IpSb = NULL;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));
++}
++
++// Test Description
++// Verify that an unknown option with a length of 0 and type of <unknown> does not cause an infinite loop
++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength0) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = 23;   // Unknown Option
++  optionHeader.Length = 0;    // This will cause an infinite loop if the function is not working correctly
++
++  // This should be a valid option even though the length is 0
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that an unknown option with a length of 1 and type of <unknown> does not cause an infinite loop
++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength1) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = 23;   // Unknown Option
++  optionHeader.Length = 1;    // This will cause an infinite loop if the function is not working correctly
++
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that an unknown option with a length of 2 and type of <unknown> does not cause an infinite loop
++TEST_F (Ip6IsOptionValidTest, VerifyIpSkipUnknownOption) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = 23;   // Unknown Option
++  optionHeader.Length = 2;    // Valid length for an unknown option
++
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that Ip6OptionPad1 is valid with a length of 0
++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPad1) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPad1;
++  optionHeader.Length = 0;
++
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that Ip6OptionPadN doesn't overflow with various lengths
++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPadN) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPadN;
++  optionHeader.Length = 0xFF;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++  optionHeader.Length = 0xFE;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++  optionHeader.Length = 0xFD;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++  optionHeader.Length = 0xFC;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify an unknown option doesn't cause an infinite loop with various lengths
++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLengthAttemptOverflow) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = 23;   // Unknown Option
++  optionHeader.Length = 0xFF;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++  optionHeader.Length = 0xFE;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++  optionHeader.Length = 0xFD;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++
++  optionHeader.Length = 0xFC;
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
++}
++
++// Test Description
++// Verify that the function supports multiple options
++TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) {
++  UINT16   HdrLen;
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  UINT8              ExtHdr[1024] = { 0 };
++  UINT8              *Cursor      = ExtHdr;
++  IP6_OPTION_HEADER  *Option      = (IP6_OPTION_HEADER *)ExtHdr;
++
++  // Let's start chaining options
++
++  Option->Type   = 23;   // Unknown Option
++  Option->Length = 0xFC;
++
++  Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
++
++  Option       = (IP6_OPTION_HEADER *)Cursor;
++  Option->Type = Ip6OptionPad1;
++
++  Cursor += sizeof (1);
++
++  // Type and length aren't processed, instead it just moves the pointer forward by 4 bytes
++  Option         = (IP6_OPTION_HEADER *)Cursor;
++  Option->Type   = Ip6OptionRouterAlert;
++  Option->Length = 4;
++
++  Cursor += sizeof (IP6_OPTION_HEADER) + 4;
++
++  Option         = (IP6_OPTION_HEADER *)Cursor;
++  Option->Type   = Ip6OptionPadN;
++  Option->Length = 0xFC;
++
++  Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
++
++  Option         = (IP6_OPTION_HEADER *)Cursor;
++  Option->Type   = Ip6OptionRouterAlert;
++  Option->Length = 4;
++
++  Cursor += sizeof (IP6_OPTION_HEADER) + 4;
++
++  // Total 524
++
++  HdrLen = (UINT16)(Cursor - ExtHdr);
++
++  EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0));
++}
++
++// Test Description
++// Verify that a OptionLength that is too small fails
++TEST_F (Ip6IsOptionValidTest, VerifyOptionLengthTooSmall) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPad1;
++  optionHeader.Length = 0;
++
++  EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, 0, 0));
++}
++
++// Test Description
++// Verify that a OptionLength that is too large fails
++TEST_F (Ip6IsOptionValidTest, VerifyOptionLengthTooLarge) {
++  NET_BUF  Packet = { 0 };
++  // we need to define enough of the packet to make the function work
++  // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
++  UINT32  DeadCode = 0xDeadC0de;
++  // Don't actually use this pointer, just pass it to the function, nothing will be done with it
++  IP6_SERVICE  *IpSb = (IP6_SERVICE *)&DeadCode;
++
++  EFI_IPv6_ADDRESS  SourceAddress      = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IPv6_ADDRESS  DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
++  EFI_IP6_HEADER    Ip6Header          = { 0 };
++
++  Ip6Header.SourceAddress      = SourceAddress;
++  Ip6Header.DestinationAddress = DestinationAddress;
++  Packet.Ip.Ip6                = &Ip6Header;
++
++  IP6_OPTION_HEADER  optionHeader;
++
++  optionHeader.Type   = Ip6OptionPad1;
++  optionHeader.Length = 0;
++
++  EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, MAX_UINT8, 0));
+ }
+\ No newline at end of file
+diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
+new file mode 100644
+index 0000000000..43ad56b4ab
+--- /dev/null
++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
+@@ -0,0 +1,33 @@
++#ifndef __EFI_IP6_OPTION_GOOGLE_TEST_H__
++#define __EFI_IP6_OPTION_GOOGLE_TEST_H__
++
++#include <Uefi.h>
++#include "../Ip6Impl.h"
++
++/** 
++  Validate the IP6 option format for both the packets we received
++  and that we will transmit. It will compute the ICMPv6 error message fields
++  if the option is malformatted.
++
++  @param[in]  IpSb              The IP6 service data.
++  @param[in]  Packet            The to be validated packet.
++  @param[in]  Option            The first byte of the option.
++  @param[in]  OptionLen         The length of the whole option.
++  @param[in]  Pointer           Identifies the octet offset within
++                                the invoking packet where the error was detected.
++
++
++  @retval TRUE     The option is properly formatted.
++  @retval FALSE    The option is malformatted.
++
++**/
++BOOLEAN
++Ip6IsOptionValid (
++  IN IP6_SERVICE  *IpSb,
++  IN NET_BUF      *Packet,
++  IN UINT8        *Option,
++  IN UINT16        OptionLen,
++  IN UINT32       Pointer
++  );
++
++#endif // __EFI_IP6_OPTION_GOOGLE_TEST_H__
+\ No newline at end of file
+diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+index 8ed3585c06..a95a617d98 100644
+--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+@@ -14,7 +14,7 @@
+   SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
+   BUILD_TARGETS           = NOOPT
+   SKUID_IDENTIFIER        = DEFAULT
+-  
++
+ !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+ [Packages]
+   MdePkg/MdePkg.dec
+-- 
+2.41.0
+
+
+From 813bfde4aa9b099c1eb6d9b38d3dbf3b9e3fa50d Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Mon, 18 Dec 2023 11:16:54 -0800
+Subject: [PATCH 09/12] SECURITY PATCH TCBZ4539 - CVE-2023-45234 - Patch
+
+---
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++---
+ 1 file changed, 65 insertions(+), 6 deletions(-)
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 425e0cf806..4059fae5fc 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -3,6 +3,7 @@
\r
+   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
++  Copyright (c) Microsoft Corporation\r
\r
+   SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
+@@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer (
+   }\r
+ }\r
\r
++/**\r
++  Cache the DHCPv6 DNS Server addresses\r
++\r
++  @param[in] Private               The pointer to PXEBC_PRIVATE_DATA.\r
++  @param[in] Cache6                The pointer to PXEBC_DHCP6_PACKET_CACHE.\r
++\r
++  @retval    EFI_SUCCESS           Cache the DHCPv6 DNS Server address successfully.\r
++  @retval    EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
++  @retval    EFI_DEVICE_ERROR      The DNS Server Address Length provided by a untrusted\r
++                                   option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)).\r
++*/\r
++EFI_STATUS\r
++PxeBcCacheDnsServerAddresses (\r
++  IN PXEBC_PRIVATE_DATA        *Private,\r
++  IN PXEBC_DHCP6_PACKET_CACHE  *Cache6\r
++  )\r
++{\r
++  UINT16  DnsServerLen;\r
++\r
++  DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen);\r
++  //\r
++  // Make sure that the number is nonzero\r
++  //\r
++  if (DnsServerLen == 0) {\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16)\r
++  //\r
++  if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) {\r
++    return EFI_DEVICE_ERROR;\r
++  }\r
++\r
++  //\r
++  // This code is currently written to only support a single DNS Server instead\r
++  // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior\r
++  // would be to allocate the full space requested, CopyMem all of the data,\r
++  // and then add a DnsServerCount field to Private and update additional code\r
++  // that depends on this.\r
++  //\r
++  // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen\r
++  //\r
++  // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886\r
++  //\r
++  Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));\r
++  if (Private->DnsServer == NULL) {\r
++    return EFI_OUT_OF_RESOURCES;\r
++  }\r
++\r
++  //\r
++  // Intentionally only copy over the first server address.\r
++  // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen\r
++  //\r
++  CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
++\r
++  return EFI_SUCCESS;\r
++}\r
++\r
+ /**\r
+   Handle the DHCPv6 offer packet.\r
\r
+@@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer (
+   UINT32                    SelectIndex;\r
+   UINT32                    Index;\r
\r
++  ASSERT (Private != NULL);\r
+   ASSERT (Private->SelectIndex > 0);\r
+   SelectIndex = (UINT32)(Private->SelectIndex - 1);\r
+   ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM);\r
+@@ -1342,15 +1403,13 @@ PxeBcHandleDhcp6Offer (
+   Status = EFI_SUCCESS;\r
\r
+   //\r
+-  // First try to cache DNS server address if DHCP6 offer provides.\r
++  // First try to cache DNS server addresses if DHCP6 offer provides.\r
+   //\r
+   if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {\r
+-    Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));\r
+-    if (Private->DnsServer == NULL) {\r
+-      return EFI_OUT_OF_RESOURCES;\r
++    Status = PxeBcCacheDnsServerAddresses (Private, Cache6);\r
++    if (EFI_ERROR (Status)) {\r
++      return Status;\r
+     }\r
+-\r
+-    CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
+   }\r
\r
+   if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {\r
+-- 
+2.41.0
+
+
+From 688eb3679f795d8699d09acc7a8c2322b389c440 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Mon, 18 Dec 2023 11:17:25 -0800
+Subject: [PATCH 10/12] SECURITY PATCH TCBZ4539 - CVE-2023-45234 - Host Based
+ Unit Test
+
+---
+ NetworkPkg/Test/NetworkPkgHostTest.dsc        |   1 +
+ .../GoogleTest/PxeBcDhcp6GoogleTest.cpp       | 301 ++++++++++++++++++
+ .../GoogleTest/PxeBcDhcp6GoogleTest.h         |  48 +++
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp     |  21 ++
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.inf     |  47 +++
+ 5 files changed, 418 insertions(+)
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+ create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+
+diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+index a95a617d98..b9d031a611 100644
+--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+@@ -26,6 +26,7 @@
+   #
+   NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+   NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
++  NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+ # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
+ [LibraryClasses]
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+new file mode 100644
+index 0000000000..9ee805a284
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+@@ -0,0 +1,301 @@
++/** @file\r
++  Host based unit test for PxeBcDhcp6.c.\r
++\r
++  Copyright (c) Microsoft Corporation\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <gtest/gtest.h>\r
++\r
++extern "C" {\r
++#include <Uefi.h>\r
++#include <Library/BaseLib.h>\r
++#include <Library/DebugLib.h>\r
++#include "../PxeBcImpl.h"\r
++#include "../PxeBcDhcp6.h"\r
++#include "PxeBcDhcp6GoogleTest.h"\r
++}\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++// Definitions\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++#define PACKET_SIZE  (1500)\r
++\r
++typedef struct {\r
++  UINT16    OptionCode;   // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)\r
++  UINT16    OptionLen;    // The length of the option (e.g., 16 bytes)\r
++  UINT8     ServerId[16]; // The 16-byte DHCPv6 Server Identifier\r
++} DHCP6_OPTION_SERVER_ID;\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++/// Symbol Definitions\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++EFI_STATUS\r
++MockUdpWrite (\r
++  IN EFI_PXE_BASE_CODE_PROTOCOL      *This,\r
++  IN UINT16                          OpFlags,\r
++  IN EFI_IP_ADDRESS                  *DestIp,\r
++  IN EFI_PXE_BASE_CODE_UDP_PORT      *DestPort,\r
++  IN EFI_IP_ADDRESS                  *GatewayIp   OPTIONAL,\r
++  IN EFI_IP_ADDRESS                  *SrcIp       OPTIONAL,\r
++  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *SrcPort     OPTIONAL,\r
++  IN UINTN                           *HeaderSize  OPTIONAL,\r
++  IN VOID                            *HeaderPtr   OPTIONAL,\r
++  IN UINTN                           *BufferSize,\r
++  IN VOID                            *BufferPtr\r
++  )\r
++{\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++EFI_STATUS\r
++MockUdpRead (\r
++  IN EFI_PXE_BASE_CODE_PROTOCOL      *This,\r
++  IN UINT16                          OpFlags,\r
++  IN OUT EFI_IP_ADDRESS              *DestIp      OPTIONAL,\r
++  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *DestPort    OPTIONAL,\r
++  IN OUT EFI_IP_ADDRESS              *SrcIp       OPTIONAL,\r
++  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *SrcPort     OPTIONAL,\r
++  IN UINTN                           *HeaderSize  OPTIONAL,\r
++  IN VOID                            *HeaderPtr   OPTIONAL,\r
++  IN OUT UINTN                       *BufferSize,\r
++  IN VOID                            *BufferPtr\r
++  )\r
++{\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++EFI_STATUS\r
++MockConfigure (\r
++  IN EFI_UDP6_PROTOCOL     *This,\r
++  IN EFI_UDP6_CONFIG_DATA  *UdpConfigData OPTIONAL\r
++  )\r
++{\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++// Needed by PxeBcSupport\r
++EFI_STATUS\r
++EFIAPI\r
++QueueDpc (\r
++  IN EFI_TPL            DpcTpl,\r
++  IN EFI_DPC_PROCEDURE  DpcProcedure,\r
++  IN VOID               *DpcContext    OPTIONAL\r
++  )\r
++{\r
++  return EFI_SUCCESS;\r
++}\r
++\r
++///////////////////////////////////////////////////////////////////////////////\r
++// PxeBcHandleDhcp6OfferTest Tests\r
++///////////////////////////////////////////////////////////////////////////////\r
++\r
++class PxeBcHandleDhcp6OfferTest : public ::testing::Test {\r
++public:\r
++PXEBC_PRIVATE_DATA Private = { 0 };\r
++EFI_UDP6_PROTOCOL Udp6Read;\r
++EFI_PXE_BASE_CODE_MODE Mode = { 0 };\r
++\r
++protected:\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++  Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);\r
++\r
++  // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL\r
++  // The function under test really only needs the following:\r
++  //  UdpWrite\r
++  //  UdpRead\r
++\r
++  Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;\r
++  Private.PxeBc.UdpRead  = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;\r
++\r
++  // Need to setup EFI_UDP6_PROTOCOL\r
++  // The function under test really only needs the following:\r
++  //  Configure\r
++\r
++  Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;\r
++  Private.Udp6Read   = &Udp6Read;\r
++\r
++  // Need to setup the EFI_PXE_BASE_CODE_MODE\r
++  Private.PxeBc.Mode = &Mode;\r
++\r
++  // for this test it doesn't really matter what the Dhcpv6 ack is set to\r
++}\r
++\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++  if (Private.Dhcp6Request != NULL) {\r
++    FreePool (Private.Dhcp6Request);\r
++  }\r
++\r
++  // Clean up any resources or variables\r
++}\r
++};\r
++\r
++// Note:\r
++// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a\r
++// properly setup Private structure. Attempting to properly test this function\r
++// without a signficant refactor is a fools errand. Instead, we will test\r
++// that we can prevent an overflow in the function.\r
++TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {\r
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
++\r
++  Private.SelectIndex = 1; // SelectIndex is 1-based\r
++  Cache6              = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++  // Setup the DHCPv6 offer packet\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (1337);\r
++\r
++  ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);\r
++}\r
++\r
++class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {\r
++public:\r
++PXEBC_PRIVATE_DATA Private = { 0 };\r
++\r
++protected:\r
++// Add any setup code if needed\r
++virtual void\r
++SetUp (\r
++  )\r
++{\r
++}\r
++\r
++// Add any cleanup code if needed\r
++virtual void\r
++TearDown (\r
++  )\r
++{\r
++}\r
++};\r
++\r
++// Test Description\r
++// Test that we cache the DNS server address from the DHCPv6 offer packet\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {\r
++  UINT8                     SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };\r
++  EFI_DHCP6_PACKET_OPTION   *Option;\r
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
++\r
++  Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));\r
++  ASSERT_NE (Option, nullptr);\r
++\r
++  Option->OpCode = DHCP6_OPT_SERVER_ID;\r
++  Option->OpLen  = NTOHS (sizeof (SearchPattern));\r
++  CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));\r
++\r
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;\r
++\r
++  Private.DnsServer = nullptr;\r
++\r
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);\r
++  ASSERT_NE (Private.DnsServer, nullptr);\r
++  ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);\r
++\r
++  if (Private.DnsServer) {\r
++    FreePool (Private.DnsServer);\r
++  }\r
++\r
++  if (Option) {\r
++    FreePool (Option);\r
++  }\r
++}\r
++// Test Description\r
++// Test that we can prevent an overflow in the function\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {\r
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
++\r
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++  // Setup the DHCPv6 offer packet\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (1337);\r
++\r
++  Private.DnsServer = NULL;\r
++\r
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);\r
++  ASSERT_EQ (Private.DnsServer, nullptr);\r
++\r
++  if (Private.DnsServer) {\r
++    FreePool (Private.DnsServer);\r
++  }\r
++}\r
++\r
++// Test Description\r
++// Test that we can prevent an underflow in the function\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {\r
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
++\r
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++  // Setup the DHCPv6 offer packet\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (2);\r
++\r
++  Private.DnsServer = NULL;\r
++\r
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);\r
++  ASSERT_EQ (Private.DnsServer, nullptr);\r
++\r
++  if (Private.DnsServer) {\r
++    FreePool (Private.DnsServer);\r
++  }\r
++}\r
++\r
++\r
++// Test Description\r
++// Test that we can handle recursive dns (multiple dns entries)\r
++TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {\r
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
++\r
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
++  // Setup the DHCPv6 offer packet\r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
++\r
++  EFI_IPv6_ADDRESS addresses[2] = {\r
++    // 2001:db8:85a3::8a2e:370:7334\r
++    {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},\r
++    // fe80::d478:91c3:ecd7:4ff9\r
++    {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9}\r
++  };\r
++\r
++\r
++  CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));\r
++  \r
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (sizeof(addresses));\r
++\r
++  Private.DnsServer = NULL;\r
++\r
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);\r
++\r
++  ASSERT_NE (Private.DnsServer, nullptr);\r
++  \r
++  //\r
++  // This is expected to fail until DnsServer supports multiple DNS servers \r
++  //\r
++  // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886\r
++  //\r
++  ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);\r
++\r
++  if (Private.DnsServer) {\r
++    FreePool (Private.DnsServer);\r
++  }\r
++}\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+new file mode 100644
+index 0000000000..724ee468cb
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+@@ -0,0 +1,48 @@
++/** @file\r
++  \r
++  This file exposes the internal interfaces which may be unit tested\r
++  for the PxeBcDhcp6Dxe driver.\r
++\r
++  Copyright (c) Microsoft Corporation.<BR>\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#ifndef __PXE_BC_DHCP6_GOOGLE_TEST_H__\r
++#define __PXE_BC_DHCP6_GOOGLE_TEST_H__\r
++\r
++// Minimal includes needed to compile\r
++#include <Uefi.h>\r
++#include "../PxeBcImpl.h"\r
++\r
++/**\r
++  Handle the DHCPv6 offer packet.\r
++\r
++  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
++\r
++  @retval     EFI_SUCCESS           Handled the DHCPv6 offer packet successfully.\r
++  @retval     EFI_NO_RESPONSE       No response to the following request packet.\r
++  @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
++  @retval     EFI_BUFFER_TOO_SMALL  Can't cache the offer pacet.\r
++\r
++**/\r
++EFI_STATUS\r
++PxeBcHandleDhcp6Offer (\r
++  IN PXEBC_PRIVATE_DATA  *Private\r
++  );\r
++\r
++  /**\r
++  Cache the DHCPv6 Server address\r
++\r
++  @param[in] Private               The pointer to PXEBC_PRIVATE_DATA.\r
++  @param[in] Cache6                The pointer to PXEBC_DHCP6_PACKET_CACHE.\r
++\r
++  @retval    EFI_SUCCESS           Cache the DHCPv6 Server address successfully.\r
++  @retval    EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
++  @retval    EFI_DEVICE_ERROR      Failed to cache the DHCPv6 Server address.\r
++*/\r
++EFI_STATUS\r
++PxeBcCacheDnsServerAddresses (\r
++  IN PXEBC_PRIVATE_DATA        *Private,\r
++  IN PXEBC_DHCP6_PACKET_CACHE  *Cache6\r
++  );\r
++\r
++#endif // __PXE_BC_DHCP6_GOOGLE_TEST_H__
+\ No newline at end of file
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+new file mode 100644
+index 0000000000..cc295f5c88
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+@@ -0,0 +1,21 @@
++/** @file\r
++  Acts as the main entry point for the tests for the UefiPxeBcDxe module.\r
++  Copyright (c) Microsoft Corporation\r
++  SPDX-License-Identifier: BSD-2-Clause-Patent\r
++**/\r
++#include <gtest/gtest.h>\r
++\r
++////////////////////////////////////////////////////////////////////////////////\r
++// Add test files here\r
++// Google Test will only pick up the tests from the files that are included\r
++// here.\r
++////////////////////////////////////////////////////////////////////////////////\r
++#include "PxeBcDhcp6GoogleTest.cpp"\r
++\r
++////////////////////////////////////////////////////////////////////////////////\r
++// Run the tests\r
++////////////////////////////////////////////////////////////////////////////////\r
++int main(int argc, char* argv[]) {\r
++  testing::InitGoogleTest (&argc, argv);\r
++  return RUN_ALL_TESTS ();\r
++}
+\ No newline at end of file
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+new file mode 100644
+index 0000000000..c2fd7ae7a9
+--- /dev/null
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+@@ -0,0 +1,47 @@
++## @file\r
++# Unit test suite for the UefiPxeBcDxe using Google Test\r
++#\r
++# Copyright (c) Microsoft Corporation.<BR>\r
++# SPDX-License-Identifier: BSD-2-Clause-Patent\r
++##\r
++[Defines]\r
++INF_VERSION    = 0x00010005\r
++BASE_NAME      = UefiPxeBcDxeGoogleTest\r
++FILE_GUID      = 77D45C64-EC1E-4174-887B-886E89FD1EDF\r
++MODULE_TYPE    = HOST_APPLICATION\r
++VERSION_STRING = 1.0\r
++\r
++#\r
++# The following information is for reference only and not required by the build tools.\r
++#\r
++#  VALID_ARCHITECTURES           = IA32 X64\r
++#\r
++    \r
++[Sources]\r
++  UefiPxeBcDxeGoogleTest.cpp\r
++  PxeBcDhcp6GoogleTest.cpp\r
++  ../PxeBcDhcp6.c\r
++  ../PxeBcSupport.c\r
++\r
++[Packages]\r
++  MdePkg/MdePkg.dec\r
++  MdeModulePkg/MdeModulePkg.dec\r
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
++  NetworkPkg/NetworkPkg.dec\r
++\r
++[LibraryClasses]\r
++  GoogleTestLib\r
++  DebugLib\r
++  NetLib\r
++  PcdLib\r
++\r
++[Protocols]\r
++  gEfiDhcp6ServiceBindingProtocolGuid\r
++  gEfiDns6ServiceBindingProtocolGuid\r
++  gEfiDns6ProtocolGuid\r
++\r
++[Pcd]\r
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType\r
++\r
++[Guids]\r
++  gZeroGuid
+\ No newline at end of file
+-- 
+2.41.0
+
+
+From 4412e98d2835b0a8a0c80763bb1ef4d62015aa12 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Mon, 18 Dec 2023 12:45:31 -0800
+Subject: [PATCH 11/12] SECURITY PATCH TCBZ4540 - CVE-2023-45235 - Patch
+
+---
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 85 +++++++++++++++++++++-------
+ NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++
+ 2 files changed, 83 insertions(+), 19 deletions(-)
+
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 4059fae5fc..a3b977fe2a 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -887,6 +887,7 @@ PxeBcRequestBootService (
+   EFI_STATUS                       Status;\r
+   EFI_DHCP6_PACKET                 *IndexOffer;\r
+   UINT8                            *Option;\r
++  UINTN                            DiscoverLenNeeded;\r
\r
+   PxeBc      = &Private->PxeBc;\r
+   Request    = Private->Dhcp6Request;\r
+@@ -898,8 +899,9 @@ PxeBcRequestBootService (
+   if (Request == NULL) {\r
+     return EFI_DEVICE_ERROR;\r
+   }\r
+-\r
+-  Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));\r
++  \r
++  DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);\r
++  Discover         = AllocateZeroPool (DiscoverLenNeeded);\r
+   if (Discover == NULL) {\r
+     return EFI_OUT_OF_RESOURCES;\r
+   }\r
+@@ -924,16 +926,34 @@ PxeBcRequestBootService (
+                DHCP6_OPT_SERVER_ID\r
+                );\r
+     if (Option == NULL) {\r
+-      return EFI_NOT_FOUND;\r
++      Status = EFI_NOT_FOUND;\r
++      goto ON_ERROR;\r
+     }\r
\r
+     //\r
+     // Add Server ID Option.\r
+     //\r
+     OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen);\r
+-    CopyMem (DiscoverOpt, Option, OpLen + 4);\r
+-    DiscoverOpt += (OpLen + 4);\r
+-    DiscoverLen += (OpLen + 4);\r
++\r
++    //\r
++    // Check that the minimum and maximum requirements are met\r
++    //\r
++    if (OpLen < PXEBC_MIN_SIZE_OF_DUID || OpLen > PXEBC_MAX_SIZE_OF_DUID) {\r
++      Status = EFI_INVALID_PARAMETER;\r
++      goto ON_ERROR;\r
++    }\r
++\r
++    //\r
++    // Check that the option length is valid.\r
++    //\r
++    if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) {\r
++      Status = EFI_OUT_OF_RESOURCES;\r
++      goto ON_ERROR;\r
++    }\r
++\r
++    CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++    DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++    DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+   }\r
\r
+   while (RequestLen < Request->Length) {\r
+@@ -944,16 +964,25 @@ PxeBcRequestBootService (
+         (OpCode != DHCP6_OPT_SERVER_ID)\r
+         )\r
+     {\r
++\r
++      //\r
++      // Check that the option length is valid.\r
++      //\r
++      if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {\r
++        Status = EFI_OUT_OF_RESOURCES;\r
++        goto ON_ERROR;\r
++      }\r
++\r
+       //\r
+       // Copy all the options except IA option and Server ID\r
+       //\r
+-      CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);\r
+-      DiscoverOpt += (OpLen + 4);\r
+-      DiscoverLen += (OpLen + 4);\r
++      CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++      DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++      DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+     }\r
\r
+-    RequestOpt += (OpLen + 4);\r
+-    RequestLen += (OpLen + 4);\r
++    RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++    RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+   }\r
\r
+   //\r
+@@ -2154,7 +2183,8 @@ PxeBcDhcp6Discover (
+   UINT16                           OpLen;\r
+   UINT32                           Xid;\r
+   EFI_STATUS                       Status;\r
+-\r
++  UINTN                            DiscoverLenNeeded;\r
++ \r
+   PxeBc    = &Private->PxeBc;\r
+   Mode     = PxeBc->Mode;\r
+   Request  = Private->Dhcp6Request;\r
+@@ -2168,8 +2198,9 @@ PxeBcDhcp6Discover (
+   if (Request == NULL) {\r
+     return EFI_DEVICE_ERROR;\r
+   }\r
+-\r
+-  Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));\r
++  \r
++  DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);\r
++  Discover         = AllocateZeroPool (DiscoverLenNeeded);\r
+   if (Discover == NULL) {\r
+     return EFI_OUT_OF_RESOURCES;\r
+   }\r
+@@ -2185,22 +2216,38 @@ PxeBcDhcp6Discover (
+   DiscoverLen             = sizeof (EFI_DHCP6_HEADER);\r
+   RequestLen              = DiscoverLen;\r
\r
++  //\r
++  // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence, \r
++  // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are \r
++  // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes,\r
++  // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with\r
++  // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously\r
++  // generated and sent. \r
++  //\r
++  // Therefore while this code looks like it could overflow, in practice it's not possible.\r
++  //\r
+   while (RequestLen < Request->Length) {\r
+     OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);\r
+     OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);\r
+     if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&\r
+         (OpCode != EFI_DHCP6_IA_TYPE_TA))\r
+     {\r
++\r
++      if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {\r
++        Status = EFI_OUT_OF_RESOURCES;\r
++        goto ON_ERROR;\r
++      }\r
++\r
+       //\r
+       // Copy all the options except IA option.\r
+       //\r
+-      CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);\r
+-      DiscoverOpt += (OpLen + 4);\r
+-      DiscoverLen += (OpLen + 4);\r
++      CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++      DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++      DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+     }\r
\r
+-    RequestOpt += (OpLen + 4);\r
+-    RequestLen += (OpLen + 4);\r
++    RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
++    RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);\r
+   }\r
\r
+   Status = PxeBc->UdpWrite (\r
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
+index c86f6d391b..2f11f0e1d9 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
+@@ -34,6 +34,23 @@
+ #define PXEBC_ADDR_START_DELIMITER        '['\r
+ #define PXEBC_ADDR_END_DELIMITER          ']'\r
\r
++//\r
++// A DUID consists of a 2-octet type code represented in network byte\r
++// order, followed by a variable number of octets that make up the\r
++// actual identifier.  The length of the DUID (not including the type\r
++// code) is at least 1 octet and at most 128 octets.\r
++//\r
++#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1)\r
++#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128)\r
++\r
++//\r
++// This define represents the combineds code and length field from\r
++// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1\r
++//\r
++#define PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN  \\r
++      (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode) + \\r
++      sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))\r
++\r
+ #define GET_NEXT_DHCP6_OPTION(Opt) \\r
+   (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \\r
+   sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1)\r
+-- 
+2.41.0
+
+
+From bef5afa1c2c6868323332dbad0478b85830cd134 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Mon, 18 Dec 2023 12:49:26 -0800
+Subject: [PATCH 12/12] SECURITY PATCH TCBZ4540 - CVE-2023-45235 - Host Based
+ Unit Test
+
+---
+ NetworkPkg/Test/NetworkPkgHostTest.dsc        |  11 +-
+ .../GoogleTest/PxeBcDhcp6GoogleTest.cpp       | 871 ++++++++++++------
+ .../GoogleTest/PxeBcDhcp6GoogleTest.h         |  18 +
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp     |  42 +-
+ .../GoogleTest/UefiPxeBcDxeGoogleTest.inf     |  92 +-
+ 5 files changed, 661 insertions(+), 373 deletions(-)
+
+diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+index b9d031a611..e6c55692a1 100644
+--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
+@@ -26,7 +26,10 @@
+   #
+   NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+   NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
+-  NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
++  NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf {
++    <LibraryClasses>
++      UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
++  }
+ # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
+ [LibraryClasses]
+@@ -88,11 +91,9 @@
+   # This library provides the instrinsic functions generated by a given compiler.
+   # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
+   #
+-  # MU_CHANGE Start
+-!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
+-  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
++!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022
++  NULL|MdePkg/Library/CompilerIntrinsicsLib/ArmCompilerIntrinsicsLib.inf
+ !endif
+-  # MU_CHANGE End
+   NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+ [LibraryClasses.ARM]
+   RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+index 9ee805a284..665aff7d72 100644
+--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+@@ -1,301 +1,570 @@
+-/** @file\r
+-  Host based unit test for PxeBcDhcp6.c.\r
+-\r
+-  Copyright (c) Microsoft Corporation\r
+-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-**/\r
+-#include <gtest/gtest.h>\r
+-\r
+-extern "C" {\r
+-#include <Uefi.h>\r
+-#include <Library/BaseLib.h>\r
+-#include <Library/DebugLib.h>\r
+-#include "../PxeBcImpl.h"\r
+-#include "../PxeBcDhcp6.h"\r
+-#include "PxeBcDhcp6GoogleTest.h"\r
+-}\r
+-\r
+-///////////////////////////////////////////////////////////////////////////////\r
+-// Definitions\r
+-///////////////////////////////////////////////////////////////////////////////\r
+-\r
+-#define PACKET_SIZE  (1500)\r
+-\r
+-typedef struct {\r
+-  UINT16    OptionCode;   // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)\r
+-  UINT16    OptionLen;    // The length of the option (e.g., 16 bytes)\r
+-  UINT8     ServerId[16]; // The 16-byte DHCPv6 Server Identifier\r
+-} DHCP6_OPTION_SERVER_ID;\r
+-\r
+-///////////////////////////////////////////////////////////////////////////////\r
+-/// Symbol Definitions\r
+-///////////////////////////////////////////////////////////////////////////////\r
+-\r
+-EFI_STATUS\r
+-MockUdpWrite (\r
+-  IN EFI_PXE_BASE_CODE_PROTOCOL      *This,\r
+-  IN UINT16                          OpFlags,\r
+-  IN EFI_IP_ADDRESS                  *DestIp,\r
+-  IN EFI_PXE_BASE_CODE_UDP_PORT      *DestPort,\r
+-  IN EFI_IP_ADDRESS                  *GatewayIp   OPTIONAL,\r
+-  IN EFI_IP_ADDRESS                  *SrcIp       OPTIONAL,\r
+-  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *SrcPort     OPTIONAL,\r
+-  IN UINTN                           *HeaderSize  OPTIONAL,\r
+-  IN VOID                            *HeaderPtr   OPTIONAL,\r
+-  IN UINTN                           *BufferSize,\r
+-  IN VOID                            *BufferPtr\r
+-  )\r
+-{\r
+-  return EFI_SUCCESS;\r
+-}\r
+-\r
+-EFI_STATUS\r
+-MockUdpRead (\r
+-  IN EFI_PXE_BASE_CODE_PROTOCOL      *This,\r
+-  IN UINT16                          OpFlags,\r
+-  IN OUT EFI_IP_ADDRESS              *DestIp      OPTIONAL,\r
+-  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *DestPort    OPTIONAL,\r
+-  IN OUT EFI_IP_ADDRESS              *SrcIp       OPTIONAL,\r
+-  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *SrcPort     OPTIONAL,\r
+-  IN UINTN                           *HeaderSize  OPTIONAL,\r
+-  IN VOID                            *HeaderPtr   OPTIONAL,\r
+-  IN OUT UINTN                       *BufferSize,\r
+-  IN VOID                            *BufferPtr\r
+-  )\r
+-{\r
+-  return EFI_SUCCESS;\r
+-}\r
+-\r
+-EFI_STATUS\r
+-MockConfigure (\r
+-  IN EFI_UDP6_PROTOCOL     *This,\r
+-  IN EFI_UDP6_CONFIG_DATA  *UdpConfigData OPTIONAL\r
+-  )\r
+-{\r
+-  return EFI_SUCCESS;\r
+-}\r
+-\r
+-// Needed by PxeBcSupport\r
+-EFI_STATUS\r
+-EFIAPI\r
+-QueueDpc (\r
+-  IN EFI_TPL            DpcTpl,\r
+-  IN EFI_DPC_PROCEDURE  DpcProcedure,\r
+-  IN VOID               *DpcContext    OPTIONAL\r
+-  )\r
+-{\r
+-  return EFI_SUCCESS;\r
+-}\r
+-\r
+-///////////////////////////////////////////////////////////////////////////////\r
+-// PxeBcHandleDhcp6OfferTest Tests\r
+-///////////////////////////////////////////////////////////////////////////////\r
+-\r
+-class PxeBcHandleDhcp6OfferTest : public ::testing::Test {\r
+-public:\r
+-PXEBC_PRIVATE_DATA Private = { 0 };\r
+-EFI_UDP6_PROTOCOL Udp6Read;\r
+-EFI_PXE_BASE_CODE_MODE Mode = { 0 };\r
+-\r
+-protected:\r
+-// Add any setup code if needed\r
+-virtual void\r
+-SetUp (\r
+-  )\r
+-{\r
+-  Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);\r
+-\r
+-  // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL\r
+-  // The function under test really only needs the following:\r
+-  //  UdpWrite\r
+-  //  UdpRead\r
+-\r
+-  Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;\r
+-  Private.PxeBc.UdpRead  = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;\r
+-\r
+-  // Need to setup EFI_UDP6_PROTOCOL\r
+-  // The function under test really only needs the following:\r
+-  //  Configure\r
+-\r
+-  Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;\r
+-  Private.Udp6Read   = &Udp6Read;\r
+-\r
+-  // Need to setup the EFI_PXE_BASE_CODE_MODE\r
+-  Private.PxeBc.Mode = &Mode;\r
+-\r
+-  // for this test it doesn't really matter what the Dhcpv6 ack is set to\r
+-}\r
+-\r
+-// Add any cleanup code if needed\r
+-virtual void\r
+-TearDown (\r
+-  )\r
+-{\r
+-  if (Private.Dhcp6Request != NULL) {\r
+-    FreePool (Private.Dhcp6Request);\r
+-  }\r
+-\r
+-  // Clean up any resources or variables\r
+-}\r
+-};\r
+-\r
+-// Note:\r
+-// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a\r
+-// properly setup Private structure. Attempting to properly test this function\r
+-// without a signficant refactor is a fools errand. Instead, we will test\r
+-// that we can prevent an overflow in the function.\r
+-TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {\r
+-  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
+-  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
+-\r
+-  Private.SelectIndex = 1; // SelectIndex is 1-based\r
+-  Cache6              = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
+-\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
+-  // Setup the DHCPv6 offer packet\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (1337);\r
+-\r
+-  ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);\r
+-}\r
+-\r
+-class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {\r
+-public:\r
+-PXEBC_PRIVATE_DATA Private = { 0 };\r
+-\r
+-protected:\r
+-// Add any setup code if needed\r
+-virtual void\r
+-SetUp (\r
+-  )\r
+-{\r
+-}\r
+-\r
+-// Add any cleanup code if needed\r
+-virtual void\r
+-TearDown (\r
+-  )\r
+-{\r
+-}\r
+-};\r
+-\r
+-// Test Description\r
+-// Test that we cache the DNS server address from the DHCPv6 offer packet\r
+-TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {\r
+-  UINT8                     SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };\r
+-  EFI_DHCP6_PACKET_OPTION   *Option;\r
+-  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
+-\r
+-  Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));\r
+-  ASSERT_NE (Option, nullptr);\r
+-\r
+-  Option->OpCode = DHCP6_OPT_SERVER_ID;\r
+-  Option->OpLen  = NTOHS (sizeof (SearchPattern));\r
+-  CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));\r
+-\r
+-  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
+-  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;\r
+-\r
+-  Private.DnsServer = nullptr;\r
+-\r
+-  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);\r
+-  ASSERT_NE (Private.DnsServer, nullptr);\r
+-  ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);\r
+-\r
+-  if (Private.DnsServer) {\r
+-    FreePool (Private.DnsServer);\r
+-  }\r
+-\r
+-  if (Option) {\r
+-    FreePool (Option);\r
+-  }\r
+-}\r
+-// Test Description\r
+-// Test that we can prevent an overflow in the function\r
+-TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {\r
+-  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
+-  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
+-\r
+-  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
+-  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
+-  // Setup the DHCPv6 offer packet\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (1337);\r
+-\r
+-  Private.DnsServer = NULL;\r
+-\r
+-  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);\r
+-  ASSERT_EQ (Private.DnsServer, nullptr);\r
+-\r
+-  if (Private.DnsServer) {\r
+-    FreePool (Private.DnsServer);\r
+-  }\r
+-}\r
+-\r
+-// Test Description\r
+-// Test that we can prevent an underflow in the function\r
+-TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {\r
+-  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
+-  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
+-\r
+-  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
+-  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
+-  // Setup the DHCPv6 offer packet\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (2);\r
+-\r
+-  Private.DnsServer = NULL;\r
+-\r
+-  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);\r
+-  ASSERT_EQ (Private.DnsServer, nullptr);\r
+-\r
+-  if (Private.DnsServer) {\r
+-    FreePool (Private.DnsServer);\r
+-  }\r
+-}\r
+-\r
+-\r
+-// Test Description\r
+-// Test that we can handle recursive dns (multiple dns entries)\r
+-TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {\r
+-  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };\r
+-  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;\r
+-\r
+-  Private.SelectIndex                         = 1; // SelectIndex is 1-based\r
+-  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;\r
+-  // Setup the DHCPv6 offer packet\r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;\r
+-\r
+-  EFI_IPv6_ADDRESS addresses[2] = {\r
+-    // 2001:db8:85a3::8a2e:370:7334\r
+-    {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},\r
+-    // fe80::d478:91c3:ecd7:4ff9\r
+-    {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9}\r
+-  };\r
+-\r
+-\r
+-  CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));\r
+-  \r
+-  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (sizeof(addresses));\r
+-\r
+-  Private.DnsServer = NULL;\r
+-\r
+-  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);\r
+-\r
+-  ASSERT_NE (Private.DnsServer, nullptr);\r
+-  \r
+-  //\r
+-  // This is expected to fail until DnsServer supports multiple DNS servers \r
+-  //\r
+-  // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886\r
+-  //\r
+-  ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);\r
+-\r
+-  if (Private.DnsServer) {\r
+-    FreePool (Private.DnsServer);\r
+-  }\r
+-}\r
++/** @file
++  Host based unit test for PxeBcDhcp6.c.
++
++  Copyright (c) Microsoft Corporation
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++#include <Library/GoogleTestLib.h>
++#include <GoogleTest/Library/MockUefiLib.h>
++#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
++
++extern "C" {
++#include <Uefi.h>
++#include <Library/BaseLib.h>
++#include <Library/DebugLib.h>
++#include "../PxeBcImpl.h"
++#include "../PxeBcDhcp6.h"
++#include "PxeBcDhcp6GoogleTest.h"
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Definitions
++///////////////////////////////////////////////////////////////////////////////
++
++#define PACKET_SIZE  (1500)
++
++typedef struct {
++  UINT16    OptionCode;   // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)
++  UINT16    OptionLen;    // The length of the option (e.g., 16 bytes)
++  UINT8     ServerId[16]; // The 16-byte DHCPv6 Server Identifier
++} DHCP6_OPTION_SERVER_ID;
++
++///////////////////////////////////////////////////////////////////////////////
++/// Symbol Definitions
++///////////////////////////////////////////////////////////////////////////////
++
++EFI_STATUS
++MockUdpWrite (
++  IN EFI_PXE_BASE_CODE_PROTOCOL      *This,
++  IN UINT16                          OpFlags,
++  IN EFI_IP_ADDRESS                  *DestIp,
++  IN EFI_PXE_BASE_CODE_UDP_PORT      *DestPort,
++  IN EFI_IP_ADDRESS                  *GatewayIp   OPTIONAL,
++  IN EFI_IP_ADDRESS                  *SrcIp       OPTIONAL,
++  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *SrcPort     OPTIONAL,
++  IN UINTN                           *HeaderSize  OPTIONAL,
++  IN VOID                            *HeaderPtr   OPTIONAL,
++  IN UINTN                           *BufferSize,
++  IN VOID                            *BufferPtr
++  )
++{
++  return EFI_SUCCESS;
++}
++
++EFI_STATUS
++MockUdpRead (
++  IN EFI_PXE_BASE_CODE_PROTOCOL      *This,
++  IN UINT16                          OpFlags,
++  IN OUT EFI_IP_ADDRESS              *DestIp      OPTIONAL,
++  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *DestPort    OPTIONAL,
++  IN OUT EFI_IP_ADDRESS              *SrcIp       OPTIONAL,
++  IN OUT EFI_PXE_BASE_CODE_UDP_PORT  *SrcPort     OPTIONAL,
++  IN UINTN                           *HeaderSize  OPTIONAL,
++  IN VOID                            *HeaderPtr   OPTIONAL,
++  IN OUT UINTN                       *BufferSize,
++  IN VOID                            *BufferPtr
++  )
++{
++  return EFI_SUCCESS;
++}
++
++EFI_STATUS
++MockConfigure (
++  IN EFI_UDP6_PROTOCOL     *This,
++  IN EFI_UDP6_CONFIG_DATA  *UdpConfigData OPTIONAL
++  )
++{
++  return EFI_SUCCESS;
++}
++
++// Needed by PxeBcSupport
++EFI_STATUS
++PxeBcDns6 (
++  IN PXEBC_PRIVATE_DATA  *Private,
++  IN     CHAR16          *HostName,
++  OUT EFI_IPv6_ADDRESS   *IpAddress
++  )
++{
++  return EFI_SUCCESS;
++}
++
++UINT32
++PxeBcBuildDhcp6Options (
++  IN  PXEBC_PRIVATE_DATA       *Private,
++  OUT EFI_DHCP6_PACKET_OPTION  **OptList,
++  IN  UINT8                    *Buffer
++  )
++{
++  return EFI_SUCCESS;
++}
++
++EFI_STATUS
++EFIAPI
++QueueDpc (
++  IN EFI_TPL            DpcTpl,
++  IN EFI_DPC_PROCEDURE  DpcProcedure,
++  IN VOID               *DpcContext    OPTIONAL
++  )
++{
++  return EFI_SUCCESS;
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcHandleDhcp6OfferTest Tests
++///////////////////////////////////////////////////////////////////////////////
++
++class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
++public:
++PXEBC_PRIVATE_DATA Private = { 0 };
++EFI_UDP6_PROTOCOL Udp6Read;
++EFI_PXE_BASE_CODE_MODE Mode = { 0 };
++
++protected:
++// Add any setup code if needed
++virtual void
++SetUp (
++  )
++{
++  Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
++
++  // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
++  // The function under test really only needs the following:
++  //  UdpWrite
++  //  UdpRead
++
++  Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
++  Private.PxeBc.UdpRead  = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
++
++  // Need to setup EFI_UDP6_PROTOCOL
++  // The function under test really only needs the following:
++  //  Configure
++
++  Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
++  Private.Udp6Read   = &Udp6Read;
++
++  // Need to setup the EFI_PXE_BASE_CODE_MODE
++  Private.PxeBc.Mode = &Mode;
++
++  // for this test it doesn't really matter what the Dhcpv6 ack is set to
++}
++
++// Add any cleanup code if needed
++virtual void
++TearDown (
++  )
++{
++  if (Private.Dhcp6Request != NULL) {
++    FreePool (Private.Dhcp6Request);
++  }
++
++  // Clean up any resources or variables
++}
++};
++
++// Note:
++// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a
++// properly setup Private structure. Attempting to properly test this function
++// without a signficant refactor is a fools errand. Instead, we will test
++// that we can prevent an overflow in the function.
++TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };
++
++  Private.SelectIndex = 1; // SelectIndex is 1-based
++  Cache6              = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++  // Setup the DHCPv6 offer packet
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (1337);
++
++  ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
++}
++
++class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
++public:
++PXEBC_PRIVATE_DATA Private = { 0 };
++
++protected:
++// Add any setup code if needed
++virtual void
++SetUp (
++  )
++{
++}
++
++// Add any cleanup code if needed
++virtual void
++TearDown (
++  )
++{
++}
++};
++
++// Test Description
++// Test that we cache the DNS server address from the DHCPv6 offer packet
++TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {
++  UINT8                     SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };
++  EFI_DHCP6_PACKET_OPTION   *Option;
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;
++
++  Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
++  ASSERT_NE (Option, nullptr);
++
++  Option->OpCode = DHCP6_OPT_SERVER_ID;
++  Option->OpLen  = NTOHS (sizeof (SearchPattern));
++  CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
++
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;
++
++  Private.DnsServer = nullptr;
++
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
++  ASSERT_NE (Private.DnsServer, nullptr);
++  ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);
++
++  if (Private.DnsServer) {
++    FreePool (Private.DnsServer);
++  }
++
++  if (Option) {
++    FreePool (Option);
++  }
++}
++// Test Description
++// Test that we can prevent an overflow in the function
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;
++
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++  // Setup the DHCPv6 offer packet
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (1337);
++
++  Private.DnsServer = NULL;
++
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
++  ASSERT_EQ (Private.DnsServer, nullptr);
++
++  if (Private.DnsServer) {
++    FreePool (Private.DnsServer);
++  }
++}
++
++// Test Description
++// Test that we can prevent an underflow in the function
++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;
++
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++  // Setup the DHCPv6 offer packet
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (2);
++
++  Private.DnsServer = NULL;
++
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
++  ASSERT_EQ (Private.DnsServer, nullptr);
++
++  if (Private.DnsServer) {
++    FreePool (Private.DnsServer);
++  }
++}
++
++
++// Test Description
++// Test that we can handle recursive dns (multiple dns entries)
++TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
++  EFI_DHCP6_PACKET_OPTION   Option  = { 0 };
++  PXEBC_DHCP6_PACKET_CACHE  *Cache6 = NULL;
++
++  Private.SelectIndex                         = 1; // SelectIndex is 1-based
++  Cache6                                      = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
++  // Setup the DHCPv6 offer packet
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
++
++  EFI_IPv6_ADDRESS addresses[2] = {
++    // 2001:db8:85a3::8a2e:370:7334
++    {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
++    // fe80::d478:91c3:ecd7:4ff9
++    {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9}
++  };
++
++
++  CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
++  
++  Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen  = NTOHS (sizeof(addresses));
++
++  Private.DnsServer = NULL;
++
++  ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
++
++  ASSERT_NE (Private.DnsServer, nullptr);
++  
++  //
++  // This is expected to fail until DnsServer supports multiple DNS servers 
++  //
++  // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
++  //
++  ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
++
++  if (Private.DnsServer) {
++    FreePool (Private.DnsServer);
++  }
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcRequestBootServiceTest Test Cases
++///////////////////////////////////////////////////////////////////////////////
++
++class PxeBcRequestBootServiceTest : public ::testing::Test {
++public:
++PXEBC_PRIVATE_DATA Private = { 0 };
++EFI_UDP6_PROTOCOL Udp6Read;
++
++protected:
++// Add any setup code if needed
++virtual void
++SetUp (
++  )
++{
++  Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
++
++  // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
++  // The function under test really only needs the following:
++  //  UdpWrite
++  //  UdpRead
++
++  Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
++  Private.PxeBc.UdpRead  = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
++
++  // Need to setup EFI_UDP6_PROTOCOL
++  // The function under test really only needs the following:
++  //  Configure
++
++  Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
++  Private.Udp6Read   = &Udp6Read;
++}
++
++// Add any cleanup code if needed
++virtual void
++TearDown (
++  )
++{
++  if (Private.Dhcp6Request != NULL) {
++    FreePool (Private.Dhcp6Request);
++  }
++
++  // Clean up any resources or variables
++}
++};
++
++TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) {
++  PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
++
++  DHCP6_OPTION_SERVER_ID  Server = { 0 };
++
++  Server.OptionCode =  HTONS (DHCP6_OPT_SERVER_ID);
++  Server.OptionLen  = HTONS (16); // valid length
++  UINT8  Index = 0;
++
++  EFI_DHCP6_PACKET  *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
++
++  UINT8  *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++  CopyMem (Cursor, &Server, sizeof (Server));
++  Cursor += sizeof (Server);
++
++  // Update the packet length
++  Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++  Packet->Size   = PACKET_SIZE;
++
++  ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
++}
++
++TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) {
++  PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
++
++  DHCP6_OPTION_SERVER_ID  Server = { 0 };
++
++  Server.OptionCode =  HTONS (DHCP6_OPT_SERVER_ID);
++  Server.OptionLen  = HTONS (1500); // This length would overflow without a check
++  UINT8  Index = 0;
++
++  EFI_DHCP6_PACKET  *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
++
++  UINT8  *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++  CopyMem (Cursor, &Server, sizeof (Server));
++  Cursor += sizeof (Server);
++
++  // Update the packet length
++  Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++  Packet->Size   = PACKET_SIZE;
++
++  ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
++}
++
++TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) {
++  EFI_DHCP6_PACKET_OPTION  RequestOpt = { 0 }; // the data section doesn't really matter
++
++  RequestOpt.OpCode = HTONS (0x1337);
++  RequestOpt.OpLen  = 0; // valid length
++
++  UINT8  Index = 0;
++
++  EFI_DHCP6_PACKET  *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
++
++  UINT8  *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++  CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++  Cursor += sizeof (RequestOpt);
++
++  // Update the packet length
++  Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++  Packet->Size   = PACKET_SIZE;
++
++  ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
++}
++
++TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) {
++  EFI_DHCP6_PACKET_OPTION  RequestOpt = { 0 }; // the data section doesn't really matter
++
++  RequestOpt.OpCode = HTONS (0x1337);
++  RequestOpt.OpLen  = 1500; // this length would overflow without a check
++
++  UINT8  Index = 0;
++
++  EFI_DHCP6_PACKET  *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
++
++  UINT8  *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
++
++  CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++  Cursor += sizeof (RequestOpt);
++
++  // Update the packet length
++  Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
++  Packet->Size   = PACKET_SIZE;
++
++  ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// PxeBcDhcp6Discover Test
++///////////////////////////////////////////////////////////////////////////////
++
++class PxeBcDhcp6DiscoverTest : public ::testing::Test {
++public:
++PXEBC_PRIVATE_DATA Private = { 0 };
++EFI_UDP6_PROTOCOL Udp6Read;
++
++protected:
++MockUefiRuntimeServicesTableLib RtServicesMock;
++
++// Add any setup code if needed
++virtual void
++SetUp (
++  )
++{
++  Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
++
++  // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
++  // The function under test really only needs the following:
++  //  UdpWrite
++  //  UdpRead
++
++  Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
++  Private.PxeBc.UdpRead  = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
++
++  // Need to setup EFI_UDP6_PROTOCOL
++  // The function under test really only needs the following:
++  //  Configure
++
++  Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
++  Private.Udp6Read   = &Udp6Read;
++}
++
++// Add any cleanup code if needed
++virtual void
++TearDown (
++  )
++{
++  if (Private.Dhcp6Request != NULL) {
++    FreePool (Private.Dhcp6Request);
++  }
++
++  // Clean up any resources or variables
++}
++};
++
++// Test Description
++// This will cause an overflow by an untrusted packet during the option parsing
++TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) {
++  EFI_IPv6_ADDRESS         DestIp     = { 0 };
++  EFI_DHCP6_PACKET_OPTION  RequestOpt = { 0 }; // the data section doesn't really matter
++
++  RequestOpt.OpCode = HTONS (0x1337);
++  RequestOpt.OpLen  = HTONS (0xFFFF); // overflow
++
++  UINT8  *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
++
++  CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++  Cursor += sizeof (RequestOpt);
++
++  Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
++
++  EXPECT_CALL (RtServicesMock, gRT_GetTime)
++    .WillOnce (::testing::Return (0));
++
++  ASSERT_EQ (
++    PxeBcDhcp6Discover (
++      &(PxeBcDhcp6DiscoverTest::Private),
++      0,
++      NULL,
++      FALSE,
++      (EFI_IP_ADDRESS *)&DestIp
++      ),
++    EFI_OUT_OF_RESOURCES
++    );
++}
++
++// Test Description
++// This will test that we can handle a packet with a valid option length
++TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) {
++  EFI_IPv6_ADDRESS         DestIp     = { 0 };
++  EFI_DHCP6_PACKET_OPTION  RequestOpt = { 0 }; // the data section doesn't really matter
++
++  RequestOpt.OpCode = HTONS (0x1337);
++  RequestOpt.OpLen  = HTONS (0x30);
++
++  UINT8  *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
++
++  CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
++  Cursor += sizeof (RequestOpt);
++
++  Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
++
++  EXPECT_CALL (RtServicesMock, gRT_GetTime)
++    .WillOnce (::testing::Return (0));
++
++  ASSERT_EQ (
++    PxeBcDhcp6Discover (
++      &(PxeBcDhcp6DiscoverTest::Private),
++      0,
++      NULL,
++      FALSE,
++      (EFI_IP_ADDRESS *)&DestIp
++      ),
++    EFI_SUCCESS
++    );
++}
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+index 724ee468cb..4d40594d51 100644
+--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
+@@ -45,4 +45,22 @@ PxeBcCacheDnsServerAddresses (
+   IN PXEBC_DHCP6_PACKET_CACHE  *Cache6\r
+   );\r
\r
++/**\r
++  Build and send out the request packet for the bootfile, and parse the reply.\r
++\r
++  @param[in]  Private               The pointer to PxeBc private data.\r
++  @param[in]  Index                 PxeBc option boot item type.\r
++\r
++  @retval     EFI_SUCCESS           Successfully discovered the boot file.\r
++  @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
++  @retval     EFI_NOT_FOUND         Can't get the PXE reply packet.\r
++  @retval     Others                Failed to discover the boot file.\r
++\r
++**/\r
++EFI_STATUS\r
++PxeBcRequestBootService (\r
++  IN  PXEBC_PRIVATE_DATA  *Private,\r
++  IN  UINT32              Index\r
++  );\r
++\r
+ #endif // __PXE_BC_DHCP6_GOOGLE_TEST_H__
+\ No newline at end of file
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+index cc295f5c88..32270d0dcb 100644
+--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
+@@ -1,21 +1,21 @@
+-/** @file\r
+-  Acts as the main entry point for the tests for the UefiPxeBcDxe module.\r
+-  Copyright (c) Microsoft Corporation\r
+-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-**/\r
+-#include <gtest/gtest.h>\r
+-\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-// Add test files here\r
+-// Google Test will only pick up the tests from the files that are included\r
+-// here.\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-#include "PxeBcDhcp6GoogleTest.cpp"\r
+-\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-// Run the tests\r
+-////////////////////////////////////////////////////////////////////////////////\r
+-int main(int argc, char* argv[]) {\r
+-  testing::InitGoogleTest (&argc, argv);\r
+-  return RUN_ALL_TESTS ();\r
+-}
+\ No newline at end of file
++/** @file
++  Acts as the main entry point for the tests for the UefiPxeBcDxe module.
++  Copyright (c) Microsoft Corporation
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++**/
++#include <gtest/gtest.h>
++
++////////////////////////////////////////////////////////////////////////////////
++// Add test files here
++// Google Test will only pick up the tests from the files that are included
++// here.
++////////////////////////////////////////////////////////////////////////////////
++#include "PxeBcDhcp6GoogleTest.cpp"
++
++////////////////////////////////////////////////////////////////////////////////
++// Run the tests
++////////////////////////////////////////////////////////////////////////////////
++int main(int argc, char* argv[]) {
++  testing::InitGoogleTest (&argc, argv);
++  return RUN_ALL_TESTS ();
++}
+diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+index c2fd7ae7a9..2d23db0e46 100644
+--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+@@ -1,47 +1,47 @@
+-## @file\r
+-# Unit test suite for the UefiPxeBcDxe using Google Test\r
+-#\r
+-# Copyright (c) Microsoft Corporation.<BR>\r
+-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+-##\r
+-[Defines]\r
+-INF_VERSION    = 0x00010005\r
+-BASE_NAME      = UefiPxeBcDxeGoogleTest\r
+-FILE_GUID      = 77D45C64-EC1E-4174-887B-886E89FD1EDF\r
+-MODULE_TYPE    = HOST_APPLICATION\r
+-VERSION_STRING = 1.0\r
+-\r
+-#\r
+-# The following information is for reference only and not required by the build tools.\r
+-#\r
+-#  VALID_ARCHITECTURES           = IA32 X64\r
+-#\r
+-    \r
+-[Sources]\r
+-  UefiPxeBcDxeGoogleTest.cpp\r
+-  PxeBcDhcp6GoogleTest.cpp\r
+-  ../PxeBcDhcp6.c\r
+-  ../PxeBcSupport.c\r
+-\r
+-[Packages]\r
+-  MdePkg/MdePkg.dec\r
+-  MdeModulePkg/MdeModulePkg.dec\r
+-  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec\r
+-  NetworkPkg/NetworkPkg.dec\r
+-\r
+-[LibraryClasses]\r
+-  GoogleTestLib\r
+-  DebugLib\r
+-  NetLib\r
+-  PcdLib\r
+-\r
+-[Protocols]\r
+-  gEfiDhcp6ServiceBindingProtocolGuid\r
+-  gEfiDns6ServiceBindingProtocolGuid\r
+-  gEfiDns6ProtocolGuid\r
+-\r
+-[Pcd]\r
+-  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType\r
+-\r
+-[Guids]\r
++## @file
++# Unit test suite for the UefiPxeBcDxe using Google Test
++#
++# Copyright (c) Microsoft Corporation.<BR>
++# SPDX-License-Identifier: BSD-2-Clause-Patent
++##
++[Defines]
++INF_VERSION    = 0x00010005
++BASE_NAME      = UefiPxeBcDxeGoogleTest
++FILE_GUID      = 77D45C64-EC1E-4174-887B-886E89FD1EDF
++MODULE_TYPE    = HOST_APPLICATION
++VERSION_STRING = 1.0
++
++#
++# The following information is for reference only and not required by the build tools.
++#
++#  VALID_ARCHITECTURES           = IA32 X64
++#
++    
++[Sources]
++  UefiPxeBcDxeGoogleTest.cpp
++  PxeBcDhcp6GoogleTest.cpp
++  ../PxeBcDhcp6.c
++  ../PxeBcSupport.c
++
++[Packages]
++  MdePkg/MdePkg.dec
++  MdeModulePkg/MdeModulePkg.dec
++  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
++  NetworkPkg/NetworkPkg.dec
++
++[LibraryClasses]
++  GoogleTestLib
++  DebugLib
++  NetLib
++  PcdLib
++
++[Protocols]
++  gEfiDhcp6ServiceBindingProtocolGuid
++  gEfiDns6ServiceBindingProtocolGuid
++  gEfiDns6ProtocolGuid
++
++[Pcd]
++  gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
++
++[Guids]
+   gZeroGuid
+\ No newline at end of file
+-- 
+2.41.0
+
diff --git a/debian/patches/CVE-2023-48733-Disable-the-Shell-when-SecureBoot-is-enabled.patch b/debian/patches/CVE-2023-48733-Disable-the-Shell-when-SecureBoot-is-enabled.patch
new file mode 100644 (file)
index 0000000..4e94178
--- /dev/null
@@ -0,0 +1,100 @@
+From: Mate Kukri <mate.kukri@canonical.com>
+Date: Wed, 6 Dec 2023 15:47:42 +0000
+Subject: Shell: Disable the Shell when SecureBoot is enabled and not in
+ SetupMode
+
+Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
+---
+ ShellPkg/Application/Shell/Shell.c   | 14 ++++++++++++++
+ ShellPkg/Application/Shell/Shell.h   |  3 +++
+ ShellPkg/Application/Shell/Shell.inf |  2 ++
+ ShellPkg/ShellPkg.dsc                |  1 +
+ 4 files changed, 20 insertions(+)
+
+Origin: https://bugs.launchpad.net/ubuntu/+source/edk2/+bug/2040137/+attachment/5741528/+files/Disable-the-Shell-when-SecureBoot-is-enabled.patch
+Bug: https://bugzilla.tianocore.org/show_bug.cgi?id=4641
+Bug-Ubuntu: https://launchpad.net/bugs/2040137
+Last-Updated: 2024-02-11
+Forwarded: https://bugzilla.tianocore.org/show_bug.cgi?id=4641#c0
+
+diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c
+index f95c799..502013d 100644
+--- a/ShellPkg/Application/Shell/Shell.c
++++ b/ShellPkg/Application/Shell/Shell.c
+@@ -357,6 +357,20 @@ UefiMain (
+   EFI_HANDLE                      ConInHandle;\r
+   EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *OldConIn;\r
+   SPLIT_LIST                      *Split;\r
++  UINT8                           SetupMode;\r
++\r
++  //\r
++  // Check for Secure Boot mode\r
++  //\r
++  if (IsSecureBootEnabled()) {\r
++    Status = GetSetupMode (&SetupMode);\r
++    if (EFI_ERROR (Status)) {\r
++        return (Status);\r
++    }\r
++    if (SetupMode != 1) {\r
++      return (EFI_SECURITY_VIOLATION);\r
++    }\r
++  }\r
\r
+   if (PcdGet8 (PcdShellSupportLevel) > 3) {\r
+     return (EFI_UNSUPPORTED);\r
+diff --git a/ShellPkg/Application/Shell/Shell.h b/ShellPkg/Application/Shell/Shell.h
+index 89b4ac6..595ec79 100644
+--- a/ShellPkg/Application/Shell/Shell.h
++++ b/ShellPkg/Application/Shell/Shell.h
+@@ -11,9 +11,11 @@
+ #define _SHELL_INTERNAL_HEADER_\r
\r
+ #include <Uefi.h>\r
++#include <UefiSecureBoot.h>\r
\r
+ #include <Guid/ShellVariableGuid.h>\r
+ #include <Guid/ShellAliasGuid.h>\r
++#include <Guid/ImageAuthentication.h>\r
\r
+ #include <Protocol/LoadedImage.h>\r
+ #include <Protocol/SimpleTextOut.h>\r
+@@ -42,6 +44,7 @@
+ #include <Library/HandleParsingLib.h>\r
+ #include <Library/FileHandleLib.h>\r
+ #include <Library/UefiHiiServicesLib.h>\r
++#include <Library/SecureBootVariableLib.h>\r
\r
+ #include "ShellParametersProtocol.h"\r
+ #include "ShellProtocol.h"\r
+diff --git a/ShellPkg/Application/Shell/Shell.inf b/ShellPkg/Application/Shell/Shell.inf
+index f1e41de..340585f 100644
+--- a/ShellPkg/Application/Shell/Shell.inf
++++ b/ShellPkg/Application/Shell/Shell.inf
+@@ -47,6 +47,7 @@
+   MdePkg/MdePkg.dec\r
+   ShellPkg/ShellPkg.dec\r
+   MdeModulePkg/MdeModulePkg.dec\r
++  SecurityPkg/SecurityPkg.dec\r
\r
+ [LibraryClasses]\r
+   BaseLib\r
+@@ -66,6 +67,7 @@
+   SortLib\r
+   HandleParsingLib\r
+   UefiHiiServicesLib\r
++  SecureBootVariableLib\r
\r
+ [Guids]\r
+   gShellVariableGuid                                      ## SOMETIMES_CONSUMES ## GUID\r
+diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
+index dd0d886..28d6a87 100644
+--- a/ShellPkg/ShellPkg.dsc
++++ b/ShellPkg/ShellPkg.dsc
+@@ -64,6 +64,7 @@
+   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
+   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
+   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf\r
++  SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf\r
\r
+ [LibraryClasses.ARM,LibraryClasses.AARCH64]\r
+   #\r
diff --git a/debian/patches/Revert-ArmVirtPkg-make-EFI_LOADER_DATA-non-executabl.patch b/debian/patches/Revert-ArmVirtPkg-make-EFI_LOADER_DATA-non-executabl.patch
new file mode 100644 (file)
index 0000000..80f0c43
--- /dev/null
@@ -0,0 +1,20 @@
+Description: Revert "ArmVirtPkg: make EFI_LOADER_DATA non-executable"
+ The versions of GRUB most distros are shipping still depend on executable
+ EFI_LOADER_DATA. Revert this upstream change until the necessary fixes are
+ more generally available.
+Author: dann frazier <dannf@debian.org>
+Bug-Debian: https://bugs.debian.org/1025656
+Forwarded: https://edk2.groups.io/g/devel/message/97814
+Last-Update: 2023-07-21
+
+--- a/ArmVirtPkg/ArmVirt.dsc.inc
++++ b/ArmVirtPkg/ArmVirt.dsc.inc
+@@ -365,7 +365,7 @@
+   # reserved ones, with the exception of LoaderData regions, of which OS loaders\r
+   # (i.e., GRUB) may assume that its contents are executable.\r
+   #\r
+-  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xC000000000007FD5\r
++  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xC000000000007FD1\r
\r
+   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|TRUE\r
\r
index 7a777c1f1138ba4cd48069a98b2a8a27d23e5c1d..5b9e8d55fbef18b1258123a258290ab8f4f9ecb1 100644 (file)
@@ -8,12 +8,12 @@ Index: edk2/BaseTools/Conf/tools_def.template
 ===================================================================
 --- edk2.orig/BaseTools/Conf/tools_def.template
 +++ edk2/BaseTools/Conf/tools_def.template
-@@ -1900,7 +1900,7 @@ DEFINE GCC_RISCV64_RC_FLAGS        = -I
+@@ -1886,7 +1886,7 @@ DEFINE GCC_LOONGARCH64_RC_FLAGS    = -I binary -O elf64-loongarch     -B loongar
  # GCC Build Flag for included header file list generation\r
  DEFINE GCC_DEPS_FLAGS              = -MMD -MF $@.deps\r
  \r
 -DEFINE GCC48_ALL_CC_FLAGS            = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings\r
-+DEFINE GCC48_ALL_CC_FLAGS            = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -fno-stack-protector -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings\r
++DEFINE GCC48_ALL_CC_FLAGS            = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -fno-stack-protector -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings\r\r
  DEFINE GCC48_IA32_X64_DLINK_COMMON   = -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x20\r
- DEFINE GCC48_IA32_CC_FLAGS           = DEF(GCC48_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -fno-stack-protector -D EFI32 -fno-asynchronous-unwind-tables -Wno-address\r
- DEFINE GCC48_X64_CC_FLAGS            = DEF(GCC48_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address\r
+ DEFINE GCC48_IA32_CC_FLAGS           = DEF(GCC48_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -fno-stack-protector -D EFI32 -fno-asynchronous-unwind-tables -Wno-address -fno-omit-frame-pointer\r
+ DEFINE GCC48_X64_CC_FLAGS            = DEF(GCC48_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address  -fno-omit-frame-pointer\r
index 31911bc9a9e31ec3f69c3a9dc14bf4e151c5121f..efd989f301517bd9af4a16d08d1f67cd4e59777f 100644 (file)
@@ -1,2 +1,7 @@
 no-stack-protector-all-archs.diff
 brotlicompress-disable.diff
+x64-baseline-abi.patch
+Revert-ArmVirtPkg-make-EFI_LOADER_DATA-non-executabl.patch
+ArmVirtPkg-disable-the-EFI_MEMORY_ATTRIBUTE-protocol.patch
+CVE-2023-45229_45237.patch
+CVE-2023-48733-Disable-the-Shell-when-SecureBoot-is-enabled.patch
diff --git a/debian/patches/x64-baseline-abi.patch b/debian/patches/x64-baseline-abi.patch
new file mode 100644 (file)
index 0000000..668f4c9
--- /dev/null
@@ -0,0 +1,20 @@
+Description: Explicitly target generic x86-64 ABI
+ The system compiler may be configured to target a higher x86-64 psABI by
+ default, so explicitly target the generic psABI to retain compatibility
+ with older machine types.
+Author: dann frazier <dannf@debian.org>
+Bug-Ubuntu: http://launchpad.net/bugs/1976267
+Forwarded: https://edk2.groups.io/g/devel/message/90447
+Last-Update: 2022-06-10
+
+--- a/BaseTools/Conf/tools_def.template
++++ b/BaseTools/Conf/tools_def.template
+@@ -1889,7 +1889,7 @@ DEFINE GCC_DEPS_FLAGS              = -MMD -MF $@.deps
+ DEFINE GCC48_ALL_CC_FLAGS            = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -fno-stack-protector -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings\r\r
+ DEFINE GCC48_IA32_X64_DLINK_COMMON   = -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x20\r
+ DEFINE GCC48_IA32_CC_FLAGS           = DEF(GCC48_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -fno-stack-protector -D EFI32 -fno-asynchronous-unwind-tables -Wno-address -fno-omit-frame-pointer\r
+-DEFINE GCC48_X64_CC_FLAGS            = DEF(GCC48_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address  -fno-omit-frame-pointer\r
++DEFINE GCC48_X64_CC_FLAGS            = DEF(GCC48_ALL_CC_FLAGS) -m64 -march=x86-64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address\r
+ DEFINE GCC48_IA32_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_DLINK_COMMON) -Wl,--entry,ReferenceAcpiTable -u ReferenceAcpiTable\r
+ DEFINE GCC48_IA32_X64_DLINK_FLAGS    = DEF(GCC48_IA32_X64_DLINK_COMMON) -Wl,--entry,$(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Wl,-Map,$(DEST_DIR_DEBUG)/$(BASE_NAME).map,--whole-archive\r
+ DEFINE GCC48_IA32_DLINK2_FLAGS       = -Wl,--defsym=PECOFF_HEADER_SIZE=0x220 DEF(GCC_DLINK2_FLAGS_COMMON)\r
diff --git a/debian/pve-edk2-firmware-aarch64.install b/debian/pve-edk2-firmware-aarch64.install
new file mode 100644 (file)
index 0000000..22cb9ee
--- /dev/null
@@ -0,0 +1,2 @@
+Build/ArmVirtQemu-AARCH64/RELEASE_*GCC*/FV/QEMU_EFI.fd /usr/share/pve-edk2-firmware/aarch64
+Build/ArmVirtQemu-AARCH64/RELEASE_*GCC*/FV/AAVMF_*.fd /usr/share/pve-edk2-firmware
diff --git a/debian/pve-edk2-firmware-legacy.install b/debian/pve-edk2-firmware-legacy.install
new file mode 100644 (file)
index 0000000..1657e3f
--- /dev/null
@@ -0,0 +1 @@
+debian/legacy-2M-builds/*      /usr/share/pve-edk2-firmware/legacy
diff --git a/debian/pve-edk2-firmware-legacy.links b/debian/pve-edk2-firmware-legacy.links
new file mode 100644 (file)
index 0000000..b2e20e4
--- /dev/null
@@ -0,0 +1,4 @@
+usr/share/pve-edk2-firmware/legacy/OVMF_CODE.fd usr/share/pve-edk2-firmware/OVMF_CODE.fd
+usr/share/pve-edk2-firmware/legacy/OVMF_CODE.secboot.fd usr/share/pve-edk2-firmware/OVMF_CODE.secboot.fd
+usr/share/pve-edk2-firmware/legacy/OVMF_VARS.fd usr/share/pve-edk2-firmware/OVMF_VARS.fd
+usr/share/pve-edk2-firmware/legacy/OVMF_VARS.ms.fd usr/share/pve-edk2-firmware/OVMF_VARS.ms.fd
diff --git a/debian/pve-edk2-firmware-ovmf.install b/debian/pve-edk2-firmware-ovmf.install
new file mode 100644 (file)
index 0000000..f4c0602
--- /dev/null
@@ -0,0 +1,5 @@
+debian/ovmf-install/OVMF_CODE*.fd      /usr/share/pve-edk2-firmware
+debian/ovmf-install/OVMF_VARS*.fd      /usr/share/pve-edk2-firmware
+debian/ovmf32-install/OVMF32_CODE*.fd          /usr/share/pve-edk2-firmware
+debian/ovmf32-install/OVMF32_VARS*.fd          /usr/share/pve-edk2-firmware
+debian/PkKek-1-snakeoil.*                      /usr/share/pve-edk2-firmware
diff --git a/debian/pve-edk2-firmware-riscv.install b/debian/pve-edk2-firmware-riscv.install
new file mode 100644 (file)
index 0000000..561eca5
--- /dev/null
@@ -0,0 +1,2 @@
+Build/RiscVVirtQemu/RELEASE_*GCC*/FV/RISCV_VIRT_CODE.fd /usr/share/pve-edk2-firmware
+Build/RiscVVirtQemu/RELEASE_*GCC*/FV/RISCV_VIRT_VARS.fd /usr/share/pve-edk2-firmware
diff --git a/debian/pve-edk2-firmware.install b/debian/pve-edk2-firmware.install
deleted file mode 100644 (file)
index 6aa70d9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-debian/ovmf-install/OVMF_CODE*.fd      /usr/share/pve-edk2-firmware
-debian/ovmf-install/OVMF_VARS*.fd      /usr/share/pve-edk2-firmware
-debian/ovmf32-install/OVMF32_CODE*.fd          /usr/share/pve-edk2-firmware
-debian/ovmf32-install/OVMF32_VARS*.fd          /usr/share/pve-edk2-firmware
-Build/ArmVirtQemu-AARCH64/RELEASE_*GCC*/FV/QEMU_EFI.fd /usr/share/pve-edk2-firmware/aarch64
-Build/ArmVirtQemu-AARCH64/RELEASE_*GCC*/FV/AAVMF_*.fd /usr/share/pve-edk2-firmware
-debian/PkKek-1-snakeoil.*                      /usr/share/pve-edk2-firmware
index 0f47cbd1250ebcadb01ebc5c24e444103549e74b..923db30a19cde002eb4e08e697f56a80ae18b011 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2019-2021 Canonical Ltd.
+# Copyright 2019-2022 Canonical Ltd.
 # Authors:
 # - dann frazier <dann.frazier@canonical.com>
 #
@@ -87,35 +87,15 @@ class EfiBootableIsoImage:
 
 
 class GrubShellBootableIsoImage(EfiBootableIsoImage):
-    def __init__(self, efi_arch, use_signed):
-        EfiArchToGrubArch = {
-            'X64': "x86_64",
-            'AA64': "arm64",
-        }
+    def __init__(self, efi_arch, shim_path, grub_path):
         efi_img = FatFsImage(64)
         efi_img.makedirs(os.path.join('EFI', 'BOOT'))
         removable_media_path = os.path.join(
             'EFI', 'BOOT', 'BOOT%s.EFI' % (efi_arch.upper())
         )
-        efi_ext = 'efi'
-        grub_subdir = "%s-efi" % EfiArchToGrubArch[efi_arch.upper()]
-        if use_signed:
-            efi_ext = "%s.signed" % (efi_ext)
-            grub_subdir = "%s-signed" % (grub_subdir)
-
-        shim_src = os.path.join(
-            os.path.sep, 'usr', 'lib', 'shim',
-            'shim%s.%s' % (efi_arch.lower(), efi_ext)
-        )
-        grub_src = os.path.join(
-            os.path.sep, 'usr', 'lib', 'grub',
-            '%s' % (grub_subdir),
-            "" if use_signed else "monolithic",
-            'grub%s.%s' % (efi_arch.lower(), efi_ext)
-        )
         grub_dest = os.path.join(
             'EFI', 'BOOT', 'GRUB%s.EFI' % (efi_arch.upper())
         )
-        efi_img.insert_file(shim_src, removable_media_path)
-        efi_img.insert_file(grub_src, grub_dest)
+        efi_img.insert_file(shim_path, removable_media_path)
+        efi_img.insert_file(grub_path, grub_dest)
         super().__init__(efi_img)
index d8aaf23c01a295408e52440dde2883785ddb67ef..b0972a85e2041d285ff0937dcb5af9190c244fb1 100644 (file)
@@ -28,6 +28,7 @@ class QemuEfiMachine(enum.Enum):
     OVMF32 = enum.auto()
     AAVMF = enum.auto()
     AAVMF32 = enum.auto()
+    RISCV64 = enum.auto()
 
 
 class QemuEfiVariant(enum.Enum):
@@ -43,11 +44,10 @@ class QemuEfiFlashSize(enum.Enum):
 
 
 class QemuCommand:
-    # Based on the args used by ovmf-vars-generator
     Qemu_Common_Params = [
         '-no-user-config', '-nodefaults',
         '-m', '256',
-        '-smp', '2,sockets=2,cores=1,threads=1',
+        '-smp', '1,sockets=1,cores=1,threads=1',
         '-display', 'none',
         '-serial', 'stdio',
     ]
@@ -58,6 +58,9 @@ class QemuCommand:
     Aavmf_Common_Params = Qemu_Common_Params + [
         '-machine', 'virt', '-device', 'virtio-serial-device',
     ]
+    RiscV_Common_Params = Qemu_Common_Params + [
+        '-machine', 'virt', '-device', 'virtio-serial-device',
+    ]
     Machine_Base_Command = {
         QemuEfiMachine.AAVMF: [
             'qemu-system-aarch64', '-cpu', 'cortex-a57',
@@ -74,6 +77,9 @@ class QemuCommand:
         QemuEfiMachine.OVMF32: [
             'qemu-system-i386', '-machine', 'q35,accel=tcg',
         ] + Ovmf_Common_Params,
+        QemuEfiMachine.RISCV64: [
+            'qemu-system-riscv64',
+        ] + RiscV_Common_Params,
     }
 
     def _get_default_flash_paths(self, machine, variant, flash_size):
@@ -116,6 +122,13 @@ class QemuCommand:
         # Remaining possibilities are OVMF variants
         if machine == QemuEfiMachine.OVMF_PC:
             assert(variant is None)
+        if machine == QemuEfiMachine.RISCV64:
+            assert(variant is None)
+            assert(flash_size == QemuEfiFlashSize.DEFAULT)
+            return (
+                '/usr/share/qemu-efi-riscv64/RISCV_VIRT_CODE.fd',
+                '/usr/share/qemu-efi-riscv64/RISCV_VIRT_VARS.fd',
+            )
         if variant == QemuEfiVariant.SNAKEOIL:
             # We provide one size - you don't get to pick.
             assert(flash_size == QemuEfiFlashSize.DEFAULT)
@@ -164,18 +177,25 @@ class QemuCommand:
         be automatically cleaned up when the object is destroyed.
         '''
         def __init__(self, code_path, vars_template_path):
+            self.params = [
+                '-drive',
+                'file=%s,if=pflash,format=raw,unit=0,readonly=on' %
+                (code_path),
+            ]
+            if vars_template_path is None:
+                self.varfile_path = None
+                return
             with tempfile.NamedTemporaryFile(delete=False) as varfile:
                 self.varfile_path = varfile.name
                 with open(vars_template_path, 'rb') as template:
                     shutil.copyfileobj(template, varfile)
-                self.params = [
-                    '-drive',
-                    'file=%s,if=pflash,format=raw,unit=0,readonly=on' %
-                    (code_path),
-                    '-drive',
-                    'file=%s,if=pflash,format=raw,unit=1,readonly=off' %
-                    (varfile.name)
-                ]
+                    self.params = self.params + [
+                        '-drive',
+                        'file=%s,if=pflash,format=raw,unit=1,readonly=off' %
+                        (varfile.name)
+                    ]
 
         def __del__(self):
+            if self.varfile_path is None:
+                return
             os.unlink(self.varfile_path)
diff --git a/debian/python/UEFI/SignedBinary.py b/debian/python/UEFI/SignedBinary.py
new file mode 100644 (file)
index 0000000..5bb33aa
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# Copyright 2022 Canonical Ltd.
+# Authors:
+# - dann frazier <dann.frazier@canonical.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import subprocess
+import tempfile
+
+
+class SignedBinary:
+    def __init__(self, binary_path, key_path, cert_path, password=None):
+        openssl_password_args = []
+        if password:
+            openssl_password_args = [
+                "-passin", f"pass:{password}"
+            ]
+        with tempfile.NamedTemporaryFile() as keytmp:
+            subprocess.check_call(
+                [
+                    "openssl", "rsa",
+                ] + openssl_password_args + [
+                    "-in", f"{key_path}",
+                    "-out", f"{keytmp.name}",
+                ]
+            )
+            with tempfile.NamedTemporaryFile(delete=False) as f:
+                self.path = f.name
+
+            subprocess.check_call(
+                [
+                    "sbsign", "--key", f"{keytmp.name}",
+                    "--cert", f"{cert_path}",
+                    binary_path, "--output", f"{self.path}"
+                ]
+            )
+
+    def __del__(self):
+        os.unlink(self.path)
index b9b800a3b4b131cd270b7a914b03083ec3da9127..7f92c166202cf1936ac5cb95ef5516d1561134fd 100755 (executable)
@@ -4,8 +4,10 @@ SHELL=/bin/bash
 
 include /usr/share/dpkg/default.mk
 
+BUILD_TYPE ?= RELEASE
 EDK2_TOOLCHAIN = GCC5
 export $(EDK2_TOOLCHAIN)_AARCH64_PREFIX=aarch64-linux-gnu-
+export $(EDK2_TOOLCHAIN)_RISCV64_PREFIX=riscv64-linux-gnu-
 
 export PYTHON3_ENABLE=TRUE
 
@@ -19,20 +21,29 @@ ifeq ($(DEB_BUILD_ARCH),arm64)
        EDK2_BUILD_ARCH=AARCH64
 endif
 
+PCD_RELEASE_DATE = $(shell date -d@$(SOURCE_DATE_EPOCH) "+%m/%d/%Y")
+PCD_FLAGS  = --pcd PcdFirmwareVendor=L"Proxmox distribution of EDK II\\0"
+PCD_FLAGS += --pcd PcdFirmwareVersionString=L"$(DEB_VERSION)\\0"
+PCD_FLAGS += --pcd PcdFirmwareReleaseDateString=L"$(PCD_RELEASE_DATE)\\0"
 COMMON_FLAGS  = -DNETWORK_HTTP_BOOT_ENABLE=TRUE
 COMMON_FLAGS += -DNETWORK_IP6_ENABLE=TRUE
 COMMON_FLAGS += -DNETWORK_TLS_ENABLE
 COMMON_FLAGS += -DSECURE_BOOT_ENABLE=TRUE
-COMMON_FLAGS += -DTPM2_ENABLE=TRUE
-OVMF_COMMON_FLAGS = $(COMMON_FLAGS)
-OVMF_2M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_2MB
+COMMON_FLAGS += -DPVSCSI_ENABLE=TRUE
+COMMON_FLAGS += $(PCD_FLAGS)
+OVMF_COMMON_FLAGS  = $(COMMON_FLAGS)
+OVMF_COMMON_FLAGS += -DTPM2_ENABLE=TRUE
 OVMF_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
-OVMF_2M_SMM_FLAGS = $(OVMF_2M_FLAGS) -DSMM_REQUIRE=TRUE
 OVMF_4M_SMM_FLAGS = $(OVMF_4M_FLAGS) -DSMM_REQUIRE=TRUE
 OVMF32_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
 OVMF32_4M_SMM_FLAGS =  $(OVMF32_4M_FLAGS) -DSMM_REQUIRE=TRUE
 
-AAVMF_FLAGS  = $(COMMON_FLAGS) -DTPM2_CONFIG_ENABLE=TRUE
+AAVMF_FLAGS  = $(COMMON_FLAGS)
+AAVMF_FLAGS += -DTPM2_ENABLE=TRUE
+AAVMF_FLAGS += -DTPM2_CONFIG_ENABLE=TRUE
+AAVMF_FLAGS += -DCAVIUM_ERRATUM_27456=TRUE
+
+RISCV64_FLAGS = $(COMMON_FLAGS)
 
 # Clear variables used internally by the edk2 build system
 undefine WORKSPACE
@@ -45,7 +56,7 @@ undefine CONF_PATH
 %:
        dh $@
 
-override_dh_auto_build: build-qemu-efi-aarch64 build-ovmf build-ovmf32
+override_dh_auto_build: build-qemu-efi-aarch64 build-ovmf build-ovmf32 build-qemu-efi-riscv64
 
 debian/setup-build-stamp:
        cp -a debian/Logo.bmp MdeModulePkg/Logo/Logo.bmp
@@ -53,21 +64,23 @@ debian/setup-build-stamp:
        make -C BaseTools ARCH=$(EDK2_BUILD_ARCH)
        touch $@
 
-OVMF_BUILD_DIR = Build/OvmfX64/RELEASE_$(EDK2_TOOLCHAIN)
-OVMF3264_BUILD_DIR = Build/Ovmf3264/RELEASE_$(EDK2_TOOLCHAIN)
+OVMF_INSTALL_DIR = debian/ovmf-install
+OVMF_BUILD_DIR = Build/OvmfX64/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
+OVMF3264_BUILD_DIR = Build/Ovmf3264/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
 OVMF_ENROLL = $(OVMF3264_BUILD_DIR)/X64/EnrollDefaultKeys.efi
 OVMF_SHELL =  $(OVMF3264_BUILD_DIR)/X64/Shell.efi
 OVMF_BINARIES = $(OVMF_ENROLL) $(OVMF_SHELL)
-OVMF_IMAGES := $(addprefix debian/ovmf-install/,OVMF_CODE.fd OVMF_CODE_4M.fd OVMF_CODE.secboot.fd OVMF_CODE_4M.secboot.fd OVMF_VARS.fd OVMF_VARS_4M.fd)
-OVMF_PREENROLLED_VARS := $(addprefix debian/ovmf-install/,OVMF_VARS.ms.fd OVMF_VARS_4M.ms.fd OVMF_VARS_4M.snakeoil.fd)
+OVMF_IMAGES := $(addprefix $(OVMF_INSTALL_DIR)/,OVMF_CODE_4M.fd OVMF_CODE_4M.secboot.fd OVMF_VARS_4M.fd)
+OVMF_PREENROLLED_VARS := $(addprefix $(OVMF_INSTALL_DIR)/,OVMF_VARS_4M.ms.fd OVMF_VARS_4M.snakeoil.fd)
 
-OVMF32_BUILD_DIR = Build/OvmfIa32/RELEASE_$(EDK2_TOOLCHAIN)
+OVMF32_INSTALL_DIR = debian/ovmf32-install
+OVMF32_BUILD_DIR = Build/OvmfIa32/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
 OVMF32_SHELL = $(OVMF32_BUILD_DIR)/IA32/Shell.efi
 OVMF32_BINARIES = $(OVMF32_SHELL)
-OVMF32_IMAGES  := $(addprefix debian/ovmf32-install/,OVMF32_CODE_4M.secboot.fd OVMF_VARS_4M.fd)
+OVMF32_IMAGES  := $(addprefix $(OVMF32_INSTALL_DIR)/,OVMF32_CODE_4M.secboot.fd OVMF32_VARS_4M.fd)
 
-QEMU_EFI_BUILD_DIR = Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/RELEASE_$(EDK2_TOOLCHAIN)
-AAVMF_BUILD_DIR = Build/ArmVirtQemu-AARCH64/RELEASE_$(EDK2_TOOLCHAIN)
+QEMU_EFI_BUILD_DIR = Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
+AAVMF_BUILD_DIR = Build/ArmVirtQemu-AARCH64/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
 AAVMF_ENROLL    = $(AAVMF_BUILD_DIR)/AARCH64/EnrollDefaultKeys.efi
 AAVMF_SHELL     = $(AAVMF_BUILD_DIR)/AARCH64/Shell.efi
 AAVMF_BINARIES  = $(AAVMF_ENROLL) $(AAVMF_SHELL)
@@ -76,58 +89,45 @@ AAVMF_VARS      = $(AAVMF_BUILD_DIR)/FV/AAVMF_VARS.fd
 AAVMF_IMAGES    = $(AAVMF_CODE) $(AAVMF_VARS)
 AAVMF_PREENROLLED_VARS = $(addprefix $(AAVMF_BUILD_DIR)/FV/,AAVMF_VARS.ms.fd AAVMF_VARS.snakeoil.fd)
 
+RISCV64_BUILD_DIR = Build/RiscVVirtQemu/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
+RISCV64_IMAGES    = $(addprefix $(RISCV64_BUILD_DIR)/FV/,RISCV_VIRT_CODE.fd RISCV_VIRT_VARS.fd)
+
 build-ovmf32: $(OVMF32_BINARIES) $(OVMF32_IMAGES)
 $(OVMF32_BINARIES) $(OVMF32_IMAGES): debian/setup-build-stamp
-       rm -rf debian/ovmf32-install
-       mkdir debian/ovmf32-install
+       rm -rf $(OVMF32_INSTALL_DIR)
+       mkdir $(OVMF32_INSTALL_DIR)
        set -e; . ./edksetup.sh; \
                build -a IA32 \
                        -t $(EDK2_TOOLCHAIN) \
                        -p OvmfPkg/OvmfPkgIa32.dsc \
-                       $(OVMF32_4M_SMM_FLAGS) -b RELEASE
+                       $(OVMF32_4M_SMM_FLAGS) -b $(BUILD_TYPE)
        cp $(OVMF32_BUILD_DIR)/FV/OVMF_CODE.fd \
-               debian/ovmf32-install/OVMF32_CODE_4M.secboot.fd
+               $(OVMF32_INSTALL_DIR)/OVMF32_CODE_4M.secboot.fd
        cp $(OVMF32_BUILD_DIR)/FV/OVMF_VARS.fd \
-               debian/ovmf32-install/OVMF32_VARS_4M.fd
+               $(OVMF32_INSTALL_DIR)/OVMF32_VARS_4M.fd
 
 build-ovmf: $(OVMF_BINARIES) $(OVMF_IMAGES) $(OVMF_PREENROLLED_VARS)
 $(OVMF_BINARIES) $(OVMF_IMAGES): debian/setup-build-stamp
-       rm -rf debian/ovmf-install
-       mkdir debian/ovmf-install
-       set -e; . ./edksetup.sh; \
-               build -a X64 \
-                       -t $(EDK2_TOOLCHAIN) \
-                       -p OvmfPkg/OvmfPkgX64.dsc \
-                       $(OVMF_2M_FLAGS) -b RELEASE
-       cp $(OVMF_BUILD_DIR)/FV/OVMF_CODE.fd \
-               debian/ovmf-install/
-       cp $(OVMF_BUILD_DIR)/FV/OVMF_VARS.fd debian/ovmf-install/
+       rm -rf $(OVMF_INSTALL_DIR)
+       mkdir $(OVMF_INSTALL_DIR)
        rm -rf Build/OvmfX64
        set -e; . ./edksetup.sh; \
                build -a IA32 -a X64 \
                        -t $(EDK2_TOOLCHAIN) \
                        -p OvmfPkg/OvmfPkgIa32X64.dsc \
-                       $(OVMF_4M_FLAGS) -b RELEASE
+                       $(OVMF_4M_FLAGS) -b $(BUILD_TYPE)
        cp $(OVMF3264_BUILD_DIR)/FV/OVMF_CODE.fd \
-               debian/ovmf-install/OVMF_CODE_4M.fd
+               $(OVMF_INSTALL_DIR)/OVMF_CODE_4M.fd
        cp $(OVMF3264_BUILD_DIR)/FV/OVMF_VARS.fd \
-               debian/ovmf-install/OVMF_VARS_4M.fd
-       rm -rf Build/OvmfX64
-       set -e; . ./edksetup.sh; \
-               build -a X64 \
-                       -t $(EDK2_TOOLCHAIN) \
-                       -p OvmfPkg/OvmfPkgX64.dsc \
-                       $(OVMF_2M_SMM_FLAGS) -b RELEASE
-       cp $(OVMF_BUILD_DIR)/FV/OVMF_CODE.fd \
-               debian/ovmf-install/OVMF_CODE.secboot.fd
+               $(OVMF_INSTALL_DIR)/OVMF_VARS_4M.fd
        rm -rf Build/OvmfX64
        set -e; . ./edksetup.sh; \
                build -a IA32 -a X64 \
                        -t $(EDK2_TOOLCHAIN) \
                        -p OvmfPkg/OvmfPkgIa32X64.dsc \
-                       $(OVMF_4M_SMM_FLAGS) -b RELEASE
+                       $(OVMF_4M_SMM_FLAGS) -b $(BUILD_TYPE)
        cp $(OVMF3264_BUILD_DIR)/FV/OVMF_CODE.fd \
-               debian/ovmf-install/OVMF_CODE_4M.secboot.fd
+               $(OVMF_INSTALL_DIR)/OVMF_CODE_4M.secboot.fd
 
 ifeq ($(call dpkg_vendor_derives_from_v1,ubuntu),yes)
 debian/PkKek-1-vendor.pem: debian/PkKek-1-Ubuntu.pem
@@ -142,59 +142,79 @@ debian/oem-string-%: debian/PkKek-1-%.pem
 
 %/AAVMF_VARS.ms.fd: %/AAVMF_CODE.fd %/AAVMF_VARS.fd debian/oem-string-vendor $(AAVMF_ENROLL) $(AAVMF_SHELL)
        PYTHONPATH=$(CURDIR)/debian/python \
-       ./debian/edk2-vars-generator.py \
+       python3 ./debian/edk2-vars-generator.py \
                -f AAVMF -e $(AAVMF_ENROLL) -s $(AAVMF_SHELL) \
                -c $(AAVMF_CODE) -V $(AAVMF_VARS) \
                -C `< debian/oem-string-vendor` -o $@
 
 %/AAVMF_VARS.snakeoil.fd: %/AAVMF_CODE.fd %/AAVMF_VARS.fd debian/oem-string-snakeoil $(AAVMF_ENROLL) $(AAVMF_SHELL)
        PYTHONPATH=$(CURDIR)/debian/python \
-       ./debian/edk2-vars-generator.py \
+       python3 ./debian/edk2-vars-generator.py \
                -f AAVMF -e $(AAVMF_ENROLL) -s $(AAVMF_SHELL) \
                -c $(AAVMF_CODE) -V $(AAVMF_VARS) \
+               --no-default \
                -C `< debian/oem-string-snakeoil` -o $@
 
 %/OVMF_VARS.ms.fd: %/OVMF_CODE.fd %/OVMF_VARS.fd debian/oem-string-vendor $(OVMF_ENROLL) $(OVMF_SHELL)
        PYTHONPATH=$(CURDIR)/debian/python \
-       ./debian/edk2-vars-generator.py \
+       python3 ./debian/edk2-vars-generator.py \
                -f OVMF -e $(OVMF_ENROLL) -s $(OVMF_SHELL) \
-               -c debian/ovmf-install/OVMF_CODE.fd \
-               -V debian/ovmf-install/OVMF_VARS.fd \
+               -c $(OVMF_INSTALL_DIR)/OVMF_CODE.fd \
+               -V $(OVMF_INSTALL_DIR)/OVMF_VARS.fd \
                -C `< debian/oem-string-vendor` -o $@
 
 %/OVMF_VARS_4M.ms.fd: %/OVMF_CODE_4M.fd %/OVMF_VARS_4M.fd debian/oem-string-vendor $(OVMF_ENROLL) $(OVMF_SHELL)
        PYTHONPATH=$(CURDIR)/debian/python \
-       ./debian/edk2-vars-generator.py \
+       python3 ./debian/edk2-vars-generator.py \
                -f OVMF_4M -e $(OVMF_ENROLL) -s $(OVMF_SHELL) \
-               -c debian/ovmf-install/OVMF_CODE_4M.fd \
-               -V debian/ovmf-install/OVMF_VARS_4M.fd \
+               -c $(OVMF_INSTALL_DIR)/OVMF_CODE_4M.fd \
+               -V $(OVMF_INSTALL_DIR)/OVMF_VARS_4M.fd \
                -C `< debian/oem-string-vendor` -o $@
 
 %/OVMF_VARS_4M.snakeoil.fd: %/OVMF_CODE_4M.fd %/OVMF_VARS_4M.fd debian/oem-string-snakeoil $(OVMF_ENROLL) $(OVMF_SHELL)
        PYTHONPATH=$(CURDIR)/debian/python \
-       ./debian/edk2-vars-generator.py \
+       python3 ./debian/edk2-vars-generator.py \
                -f OVMF_4M -e $(OVMF_ENROLL) -s $(OVMF_SHELL) \
-               -c debian/ovmf-install/OVMF_CODE_4M.fd \
-               -V debian/ovmf-install/OVMF_VARS_4M.fd \
+               -c $(OVMF_INSTALL_DIR)/OVMF_CODE_4M.fd \
+               -V $(OVMF_INSTALL_DIR)/OVMF_VARS_4M.fd \
+               --no-default \
                -C `< debian/oem-string-snakeoil` -o $@
 
 ArmPkg/Library/GccLto/liblto-aarch64.a:        ArmPkg/Library/GccLto/liblto-aarch64.s
        $($(EDK2_TOOLCHAIN)_AARCH64_PREFIX)gcc -c -fpic $< -o $@
 
+ArmPkg/Library/GccLto/liblto-arm.a: ArmPkg/Library/GccLto/liblto-arm.s
+       $($(EDK2_TOOLCHAIN)_ARM_PREFIX)gcc -c -fpic $< -o $@
+
 build-qemu-efi: debian/setup-build-stamp
        set -e; . ./edksetup.sh; \
                build -a $(EDK2_HOST_ARCH) \
                        -t $(EDK2_TOOLCHAIN) \
                        -p ArmVirtPkg/ArmVirtQemu.dsc \
-                       $(AAVMF_FLAGS) -b RELEASE
-       dd if=/dev/zero of=$(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_CODE.fd bs=1M seek=64 count=0
-       dd if=$(QEMU_EFI_BUILD_DIR)/FV/QEMU_EFI.fd of=$(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_CODE.fd conv=notrunc
-       dd if=/dev/zero of=$(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_VARS.fd bs=1M seek=64 count=0
-
-build-qemu-efi-aarch64: $(AAVMF_BINARIES) $(AAVMF_PREENROLLED_VARS)
-$(AAVMF_BINARIES): ArmPkg/Library/GccLto/liblto-aarch64.a
+                       $(AAVMF_FLAGS) -b $(BUILD_TYPE)
+       cp $(QEMU_EFI_BUILD_DIR)/FV/QEMU_EFI.fd \
+               $(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_CODE.fd
+       cp $(QEMU_EFI_BUILD_DIR)/FV/QEMU_VARS.fd \
+               $(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_VARS.fd
+       # QEMU expects 64MiB CODE and VARS files on ARM/AARCH64 architectures
+       # Truncate the firmware files to the expected size
+       truncate -s 64M $(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_CODE.fd
+       truncate -s 64M $(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_VARS.fd
+
+build-qemu-efi-aarch64: $(AAVMF_BINARIES) $(AAVMF_IMAGES) $(AAVMF_PREENROLLED_VARS)
+$(AAVMF_BINARIES) $(AAVMF_IMAGES): ArmPkg/Library/GccLto/liblto-aarch64.a
        $(MAKE) -f debian/rules build-qemu-efi EDK2_ARCH_DIR=AArch64 EDK2_HOST_ARCH=AARCH64 FW_NAME=AAVMF
 
+build-qemu-efi-riscv64:  $(RISCV64_IMAGES)
+$(RISCV64_IMAGES): debian/setup-build-stamp
+       set -e; . ./edksetup.sh; \
+               build -a RISCV64 \
+                       -t $(EDK2_TOOLCHAIN) \
+                       -p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc \
+                       $(RISCV64_FLAGS) -b $(BUILD_TYPE)
+       truncate -s 32M $(RISCV64_BUILD_DIR)/FV/RISCV_VIRT_CODE.fd
+       truncate -s 32M $(RISCV64_BUILD_DIR)/FV/RISCV_VIRT_VARS.fd
+
 override_dh_auto_clean:
        -. ./edksetup.sh; build clean
        make -C BaseTools clean
@@ -203,6 +223,7 @@ override_dh_auto_clean:
 EMBEDDED_SUBMODULES += CryptoPkg/Library/OpensslLib/openssl
 EMBEDDED_SUBMODULES += ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
 EMBEDDED_SUBMODULES += MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
+EMBEDDED_SUBMODULES += MdePkg/Library/MipiSysTLib/mipisyst
 get-orig-source:
        # Should be executed on a checkout of the upstream master branch,
        # with the debian/ directory manually copied in.
@@ -211,7 +232,7 @@ get-orig-source:
        # stuff we don't need
        set -e; cd edk2.tmp; \
        for submodule in $(EMBEDDED_SUBMODULES); do \
-               git submodule update --init $$submodule; \
+               git submodule update --depth 1 --init $$submodule; \
        done
        rm -rf edk2-$(DEB_VERSION_UPSTREAM) && \
                mkdir edk2-$(DEB_VERSION_UPSTREAM)
@@ -229,4 +250,4 @@ get-orig-source:
                edk2-$(DEB_VERSION_UPSTREAM)
        rm -rf edk2.tmp edk2-$(DEB_VERSION_UPSTREAM)
 
-.PHONY: build-ovmf build-ovmf32 build-qemu-efi build-qemu-efi-aarch64
+.PHONY: build-ovmf build-ovmf32 build-qemu-efi build-qemu-efi-aarch64 build-qemu-efi-riscv64
diff --git a/debian/source/include-binaries b/debian/source/include-binaries
new file mode 100644 (file)
index 0000000..2d86386
--- /dev/null
@@ -0,0 +1,5 @@
+debian/Logo.bmp
+debian/legacy-2M-builds/OVMF_VARS.ms.fd
+debian/legacy-2M-builds/OVMF_VARS.fd
+debian/legacy-2M-builds/OVMF_CODE.secboot.fd
+debian/legacy-2M-builds/OVMF_CODE.fd
diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides
new file mode 100644 (file)
index 0000000..d9f1573
--- /dev/null
@@ -0,0 +1,6 @@
+pve-edk2-firmware source: superfluous-file-pattern * [debian/copyright:*]
+pve-edk2-firmware source: source-is-missing [*/brotli/js/*.js]
+pve-edk2-firmware source: source-is-missing [CryptoPkg/Library/OpensslLib/openssl/krb5/*/*.htm]
+pve-edk2-firmware source: source-is-missing [CryptoPkg/Library/OpensslLib/openssl/krb5/*/*.html]
+pve-edk2-firmware source: source-is-missing [MdePkg/Library/MipiSysTLib/mipisyst/external/pugixml/docs/manual.html]
+pve-edk2-firmware source: source-is-missing [MdePkg/Library/MipiSysTLib/mipisyst/external/pugixml/docs/quickstart.html]
index cc87fdeadfea1304df2ed9621b15c4bfe8f4f695..eba17211f5f986c958e9203bf192a08e3357f933 100644 (file)
@@ -5,12 +5,15 @@ Depends:
  grub-efi-amd64-signed [amd64],
  grub-efi-arm64-signed [arm64],
  mtools [amd64 arm64],
+ openssl [amd64 arm64],
  ovmf,
  ovmf-ia32,
  python3-pexpect,
  qemu-efi-aarch64,
  qemu-efi-arm,
  qemu-system-arm,
+ qemu-system-misc,
  qemu-system-x86,
+ sbsigntool [amd64 arm64],
  shim-signed [amd64 arm64],
  xorriso [amd64 arm64],
index 391b7bf17e7bbd8382ee992ab63afda97d048da4..8b94b59df1b49400ed84a13a2265e293af3e0715 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-# Copyright 2019-2021 Canonical Ltd.
+# Copyright 2019-2022 Canonical Ltd.
 # Authors:
 # - dann frazier <dann.frazier@canonical.com>
 #
 #
 
 import enum
+import os
 import pexpect
 import subprocess
 import sys
+import time
 import unittest
 
 from UEFI.Filesystems import GrubShellBootableIsoImage
+from UEFI.SignedBinary import SignedBinary
 from UEFI.Qemu import QemuEfiMachine, QemuEfiVariant, QemuEfiFlashSize
 from UEFI import Qemu
 
@@ -31,15 +34,56 @@ DPKG_ARCH = subprocess.check_output(
     ['dpkg', '--print-architecture']
 ).decode().rstrip()
 
+EfiArchToGrubArch = {
+    'X64': "x86_64",
+    'AA64': "arm64",
+}
+
+TEST_TIMEOUT = 120
+
+
+def get_local_grub_path(efi_arch, signed=False):
+    grub_subdir = "%s-efi" % EfiArchToGrubArch[efi_arch.upper()]
+    ext = "efi"
+    if signed:
+        grub_subdir = f"{grub_subdir}-signed"
+        ext = f"{ext}.signed"
+
+    grub_path = os.path.join(
+        os.path.sep, 'usr', 'lib', 'grub',
+        '%s' % (grub_subdir),
+        "" if signed else "monolithic",
+        'grub%s.%s' % (efi_arch.lower(), ext)
+    )
+    return grub_path
+
+
+def get_local_shim_path(efi_arch, signed=False):
+    ext = 'efi'
+    if signed:
+        ext = f"{ext}.signed"
+    shim_path = os.path.join(
+        os.path.sep, 'usr', 'lib', 'shim',
+        'shim%s.%s' % (efi_arch.lower(), ext)
+    )
+    return shim_path
+
 
 class BootToShellTest(unittest.TestCase):
     debug = True
 
+    def setUp(self):
+        self.startTime = time.time()
+
+    def tearDown(self):
+        t = time.time() - self.startTime
+        sys.stdout.write("%s runtime: %.3fs\n" % (self.id(), t))
+
     def run_cmd_check_shell(self, cmd):
-        child = pexpect.spawn(' '.join(cmd))
+        child = pexpect.spawn(' '.join(cmd), encoding='UTF-8')
 
         if self.debug:
-            child.logfile = sys.stdout.buffer
+            child.logfile = sys.stdout
         try:
             while True:
                 i = child.expect(
@@ -47,7 +91,7 @@ class BootToShellTest(unittest.TestCase):
                         'Press .* or any other key to continue',
                         'Shell> '
                     ],
-                    timeout=60,
+                    timeout=TEST_TIMEOUT,
                 )
                 if i == 0:
                     child.sendline('\x1b')
@@ -56,7 +100,9 @@ class BootToShellTest(unittest.TestCase):
                     child.sendline('reset -s\r')
                     continue
         except pexpect.EOF:
-            return
+            child.close()
+            if child.exitstatus != 0:
+                self.fail("ERROR: exit code %d\n" % (child.exitstatus))
         except pexpect.TIMEOUT as err:
             self.fail("%s\n" % (err))
 
@@ -65,10 +111,10 @@ class BootToShellTest(unittest.TestCase):
             PRE_EXEC = 1
             POST_EXEC = 2
 
-        child = pexpect.spawn(' '.join(cmd))
+        child = pexpect.spawn(' '.join(cmd), encoding='UTF-8')
 
         if self.debug:
-            child.logfile = sys.stdout.buffer
+            child.logfile = sys.stdout
         try:
             state = State.PRE_EXEC
             while True:
@@ -80,7 +126,7 @@ class BootToShellTest(unittest.TestCase):
                         'grub> ',
                         'Command Error Status: Access Denied',
                     ],
-                    timeout=60,
+                    timeout=TEST_TIMEOUT,
                 )
                 if i == 0:
                     child.sendline('\x1b')
@@ -102,10 +148,12 @@ class BootToShellTest(unittest.TestCase):
                 if i == 4:
                     verified = False
                     continue
+        except pexpect.EOF:
+            child.close()
+            if child.exitstatus != 0:
+                self.fail("ERROR: exit code %d\n" % (child.exitstatus))
         except pexpect.TIMEOUT as err:
             self.fail("%s\n" % (err))
-        except pexpect.EOF:
-            pass
         self.assertEqual(should_verify, verified)
 
     def test_aavmf(self):
@@ -113,12 +161,20 @@ class BootToShellTest(unittest.TestCase):
         self.run_cmd_check_shell(q.command)
 
     @unittest.skipUnless(DPKG_ARCH == 'arm64', "Requires grub-efi-arm64")
+    @unittest.skipUnless(
+        subprocess.run(
+            ['dpkg-vendor', '--derives-from', 'Ubuntu']
+        ).returncode == 0,
+        "Debian does not provide a signed shim for arm64, see #992073"
+    )
     def test_aavmf_ms_secure_boot_signed(self):
         q = Qemu.QemuCommand(
             QemuEfiMachine.AAVMF,
             variant=QemuEfiVariant.MS,
         )
-        iso = GrubShellBootableIsoImage('AA64', use_signed=True)
+        grub = get_local_grub_path('AA64', signed=True)
+        shim = get_local_shim_path('AA64', signed=True)
+        iso = GrubShellBootableIsoImage('AA64', shim, grub)
         q.add_disk(iso.path)
         self.run_cmd_check_secure_boot(q.command, 'aa64', True)
 
@@ -128,7 +184,9 @@ class BootToShellTest(unittest.TestCase):
             QemuEfiMachine.AAVMF,
             variant=QemuEfiVariant.MS,
         )
-        iso = GrubShellBootableIsoImage('AA64', use_signed=False)
+        grub = get_local_grub_path('AA64', signed=False)
+        shim = get_local_shim_path('AA64', signed=False)
+        iso = GrubShellBootableIsoImage('AA64', shim, grub)
         q.add_disk(iso.path)
         self.run_cmd_check_secure_boot(q.command, 'aa64', False)
 
@@ -143,56 +201,6 @@ class BootToShellTest(unittest.TestCase):
         q = Qemu.QemuCommand(QemuEfiMachine.AAVMF32)
         self.run_cmd_check_shell(q.command)
 
-    def test_ovmf_pc(self):
-        q = Qemu.QemuCommand(
-            QemuEfiMachine.OVMF_PC, flash_size=QemuEfiFlashSize.SIZE_2MB,
-        )
-        self.run_cmd_check_shell(q.command)
-
-    def test_ovmf_q35(self):
-        q = Qemu.QemuCommand(
-            QemuEfiMachine.OVMF_Q35, flash_size=QemuEfiFlashSize.SIZE_2MB,
-        )
-        self.run_cmd_check_shell(q.command)
-
-    def test_ovmf_secboot(self):
-        q = Qemu.QemuCommand(
-            QemuEfiMachine.OVMF_Q35,
-            variant=QemuEfiVariant.SECBOOT,
-            flash_size=QemuEfiFlashSize.SIZE_2MB,
-        )
-        self.run_cmd_check_shell(q.command)
-
-    def test_ovmf_ms(self):
-        q = Qemu.QemuCommand(
-            QemuEfiMachine.OVMF_Q35,
-            variant=QemuEfiVariant.MS,
-            flash_size=QemuEfiFlashSize.SIZE_2MB,
-        )
-        self.run_cmd_check_shell(q.command)
-
-    @unittest.skipUnless(DPKG_ARCH == 'amd64', "amd64-only")
-    def test_ovmf_ms_secure_boot_signed(self):
-        q = Qemu.QemuCommand(
-            QemuEfiMachine.OVMF_Q35,
-            variant=QemuEfiVariant.MS,
-            flash_size=QemuEfiFlashSize.SIZE_2MB,
-        )
-        iso = GrubShellBootableIsoImage('X64', use_signed=True)
-        q.add_disk(iso.path)
-        self.run_cmd_check_secure_boot(q.command, 'x64', True)
-
-    @unittest.skipUnless(DPKG_ARCH == 'amd64', "amd64-only")
-    def test_ovmf_ms_secure_boot_unsigned(self):
-        q = Qemu.QemuCommand(
-            QemuEfiMachine.OVMF_Q35,
-            variant=QemuEfiVariant.MS,
-            flash_size=QemuEfiFlashSize.SIZE_2MB,
-        )
-        iso = GrubShellBootableIsoImage('X64', use_signed=False)
-        q.add_disk(iso.path)
-        self.run_cmd_check_secure_boot(q.command, 'x64', False)
-
     def test_ovmf_4m(self):
         q = Qemu.QemuCommand(
             QemuEfiMachine.OVMF_Q35,
@@ -230,7 +238,9 @@ class BootToShellTest(unittest.TestCase):
             variant=QemuEfiVariant.MS,
             flash_size=QemuEfiFlashSize.SIZE_4MB,
         )
-        iso = GrubShellBootableIsoImage('X64', use_signed=True)
+        grub = get_local_grub_path('X64', signed=True)
+        shim = get_local_shim_path('X64', signed=True)
+        iso = GrubShellBootableIsoImage('X64', shim, grub)
         q.add_disk(iso.path)
         self.run_cmd_check_secure_boot(q.command, 'x64', True)
 
@@ -241,7 +251,44 @@ class BootToShellTest(unittest.TestCase):
             variant=QemuEfiVariant.MS,
             flash_size=QemuEfiFlashSize.SIZE_4MB,
         )
-        iso = GrubShellBootableIsoImage('X64', use_signed=False)
+        grub = get_local_grub_path('X64', signed=False)
+        shim = get_local_shim_path('X64', signed=False)
+        iso = GrubShellBootableIsoImage('X64', shim, grub)
+        q.add_disk(iso.path)
+        self.run_cmd_check_secure_boot(q.command, 'x64', False)
+
+    @unittest.skipUnless(DPKG_ARCH == 'amd64', "amd64-only")
+    def test_ovmf_snakeoil_secure_boot_signed(self):
+        q = Qemu.QemuCommand(
+            QemuEfiMachine.OVMF_Q35,
+            variant=QemuEfiVariant.SNAKEOIL,
+        )
+        shim = SignedBinary(
+            get_local_shim_path('X64', signed=False),
+            "/usr/share/ovmf/PkKek-1-snakeoil.key",
+            "/usr/share/ovmf/PkKek-1-snakeoil.pem",
+            "snakeoil",
+        )
+        grub = SignedBinary(
+            get_local_grub_path('X64', signed=False),
+            "/usr/share/ovmf/PkKek-1-snakeoil.key",
+            "/usr/share/ovmf/PkKek-1-snakeoil.pem",
+            "snakeoil",
+        )
+        iso = GrubShellBootableIsoImage('X64', shim.path, grub.path)
+        q.add_disk(iso.path)
+        self.run_cmd_check_secure_boot(q.command, 'x64', True)
+
+    @unittest.skipUnless(DPKG_ARCH == 'amd64', "amd64-only")
+    def test_ovmf_snakeoil_secure_boot_unsigned(self):
+        q = Qemu.QemuCommand(
+            QemuEfiMachine.OVMF_Q35,
+            variant=QemuEfiVariant.SNAKEOIL,
+            flash_size=QemuEfiFlashSize.DEFAULT,
+        )
+        grub = get_local_grub_path('X64', signed=False)
+        shim = get_local_shim_path('X64', signed=False)
+        iso = GrubShellBootableIsoImage('X64', shim, grub)
         q.add_disk(iso.path)
         self.run_cmd_check_secure_boot(q.command, 'x64', False)
 
@@ -253,6 +300,9 @@ class BootToShellTest(unittest.TestCase):
         )
         self.run_cmd_check_shell(q.command)
 
+    def test_riscv64(self):
+        q = Qemu.QemuCommand(QemuEfiMachine.RISCV64)
+        self.run_cmd_check_shell(q.command)
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/edk2 b/edk2
index 16779ede2d366bfc6b702e817356ccf43425bcc8..819cfc6b42a68790a23509e4fcc58ceb70e1965e 160000 (submodule)
--- a/edk2
+++ b/edk2
@@ -1 +1 @@
-Subproject commit 16779ede2d366bfc6b702e817356ccf43425bcc8
+Subproject commit 819cfc6b42a68790a23509e4fcc58ceb70e1965e