diff --git a/.github/workflows/uki.yaml b/.github/workflows/uki.yaml new file mode 100644 index 00000000..ee3f089d --- /dev/null +++ b/.github/workflows/uki.yaml @@ -0,0 +1,60 @@ +name: UKI tests +on: + pull_request: + +concurrency: + group: ci-uki-${{ github.head_ref || github.ref }}-${{ github.repository }} + cancel-in-progress: true +env: + FORCE_COLOR: 1 +jobs: + test-uki: + runs-on: kvm + steps: + - uses: actions/checkout@v4 + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version-file: tests/go.mod + cache-dependency-path: tests/go.sum + - name: Enable KVM group perms + run: | + sudo apt-get update + sudo apt-get install -y libvirt-clients libvirt-daemon-system libvirt-daemon virtinst bridge-utils qemu qemu-system-x86 qemu-system-x86 qemu-utils qemu-kvm acl udev + # https://github.blog/changelog/2023-02-23-hardware-accelerated-android-virtualization-on-actions-windows-and-linux-larger-hosted-runners/ + # echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + # sudo udevadm control --reload-rules + # sudo udevadm trigger --name-match=kvm + # sudo usermod -a -G kvm,libvirt $USER + # + # TODO: Switch back to the above solution when we switch to the github runners + # https://askubuntu.com/a/1081326 + sudo setfacl -m u:runner:rwx /dev/kvm + - name: Install earthly + uses: Luet-lab/luet-install-action@v1.1 + with: + repository: quay.io/kairos/packages + packages: utils/earthly + - name: Build uki ISO 🔧 + run: | + # Do fedora as its the smaller uki possible + # Use immmucore master as it has patches not released for uki + # Use kairos-agent main branch as it has patches not released for uki + earthly +iso-uki --FLAVOR=opensuse-leap --KAIROS_AGENT_DEV=true --KAIROS_AGENT_DEV_BRANCH=main --IMMUCORE_DEV=true --IMMUCORE_DEV_BRANCH=master + - name: Run tests + env: + USE_QEMU: true + KVM: true + MEMORY: 4000 + CPUS: 2 + FIRMWARE: /usr/share/OVMF/OVMF_CODE.fd + run: | + export ISO=$(ls $PWD/build/kairos-core-*opensuse-leap*.iso) + cp tests/go.* . + go run github.com/onsi/ginkgo/v2/ginkgo -v --label-filter "uki" --fail-fast -r ./tests/ + - uses: actions/upload-artifact@v3 + if: failure() + with: + name: ${{ inputs.flavor }}.logs.zip + path: tests/**/logs/* + if-no-files-found: warn diff --git a/Earthfile b/Earthfile index d700b4f0..b22b8c80 100644 --- a/Earthfile +++ b/Earthfile @@ -491,8 +491,10 @@ uki-artifacts: FROM +base-image --BUILD_INITRD=false RUN /usr/bin/immucore version RUN ln -s /usr/bin/immucore /init + RUN mkdir -p /oem # be able to mount oem under here if found + RUN mkdir -p /efi # mount the esp under here if found RUN find . \( -path ./sys -prune -o -path ./run -prune -o -path ./dev -prune -o -path ./tmp -prune -o -path ./proc -prune \) -o -print | cpio -R root:root -H newc -o | gzip -2 > /tmp/initramfs.cpio.gz - RUN echo "console=tty1 console=ttyS0 net.ifnames=1 rd.immucore.debug rd.immucore.uki selinux=0" > /tmp/Cmdline + RUN echo "console=tty1 console=ttyS0 net.ifnames=1 rd.immucore.oemlabel=COS_OEM rd.immucore.oemtimeout=2 rd.immucore.debug rd.immucore.uki selinux=0" > /tmp/Cmdline RUN basename $(ls /boot/vmlinuz-* |grep -v rescue | head -n1)| sed --expression "s/vmlinuz-//g" > /tmp/Uname SAVE ARTIFACT /boot/vmlinuz Kernel SAVE ARTIFACT /etc/os-release Osrelease @@ -504,8 +506,25 @@ uki-artifacts: uki-tools-image: FROM fedora:38 # objcopy from binutils and systemd-stub from systemd - RUN dnf install -y binutils systemd-boot mtools efitools sbsigntools shim openssl + RUN dnf install -y binutils systemd-boot mtools efitools sbsigntools shim openssl systemd-ukify +# HOW TO: Generate the keys +# Platform key +# RUN openssl req -new -x509 -subj "/CN=Kairos PK/" -days 3650 -nodes -newkey rsa:2048 -sha256 -keyout PK.key -out PK.crt +# DER keys are for FW install +# RUN openssl x509 -in PK.crt -out PK.der -outform DER +# Key exchange +# RUN openssl req -new -x509 -subj "/CN=Kairos KEK/" -days 3650 -nodes -newkey rsa:2048 -sha256 -keyout KEK.key -out KEK.crt +# DER keys are for FW install +# RUN openssl x509 -in KEK.crt -out KEK.der -outform DER +# Signature DB +# RUN openssl req -new -x509 -subj "/CN=Kairos DB/" -days 3650 -nodes -newkey rsa:2048 -sha256 -keyout DB.key -out DB.crt +# DER keys are for FW install +# RUN openssl x509 -in DB.crt -out DB.der -outform DER +# But for now just use test keys pre-generated for easy testing. +# NOTE: NEVER EVER EVER use this keys for signing anything that its going outside your computer +# This is for easy testing SecureBoot locally for development purposes +# Installing this keys in other place than a VM for testing SecureBoot is irresponsible uki: ARG TARGETARCH COPY +version/VERSION ./ @@ -520,100 +539,40 @@ uki: COPY +uki-artifacts/Uname Uname COPY +uki-artifacts/Cmdline Cmdline ARG KVERSION=$(cat Uname) + COPY tests/keys/* . RUN objcopy /usr/lib/systemd/boot/efi/linuxx64.efi.stub \ - --add-section .osrel=Osrelease --set-section-flags .osrel=data,readonly \ - --add-section .cmdline=Cmdline --set-section-flags .cmdline=data,readonly \ - --add-section .initrd=Initrd --set-section-flags .initrd=data,readonly \ - --add-section .uname=Uname --set-section-flags .uname=data,readonly \ - --add-section .linux=Kernel --set-section-flags .linux=code,readonly \ - $ISO_NAME.unsigned.efi \ - --change-section-vma .osrel=0x17000 \ - --change-section-vma .cmdline=0x18000 \ - --change-section-vma .initrd=0x19000 \ - --change-section-vma .uname=0x5a0ed000 \ - --change-section-vma .linux=0x5a0ee000 - SAVE ARTIFACT Uname Uname - SAVE ARTIFACT $ISO_NAME.unsigned.efi uki.efi AS LOCAL build/$ISO_NAME.unsigned-$KVERSION.efi - - -uki-signed: - FROM +uki-tools-image - # Platform key - RUN openssl req -new -x509 -subj "/CN=Kairos PK/" -days 3650 -nodes -newkey rsa:2048 -sha256 -keyout PK.key -out PK.crt - # CER keys are for FW install - RUN openssl x509 -in PK.crt -out PK.cer -outform DER - # Key exchange - RUN openssl req -new -x509 -subj "/CN=Kairos KEK/" -days 3650 -nodes -newkey rsa:2048 -sha256 -keyout KEK.key -out KEK.crt - # CER keys are for FW install - RUN openssl x509 -in KEK.crt -out KEK.cer -outform DER - # Signature DB - RUN openssl req -new -x509 -subj "/CN=Kairos DB/" -days 3650 -nodes -newkey rsa:2048 -sha256 -keyout DB.key -out DB.crt - # CER keys are for FW install - RUN openssl x509 -in DB.crt -out DB.cer -outform DER - COPY +uki/uki.efi uki.efi - COPY +uki/Uname Uname - ARG KVERSION=$(cat Uname) - COPY +version/VERSION ./ - RUN echo "version ${VERSION}" - ARG VERSION=$(cat VERSION) - ARG TARGETARCH - ARG ISO_NAME=${OS_ID}-${VARIANT}-${FLAVOR}-${TARGETARCH}-${MODEL}-${VERSION} - - RUN sbsign --key DB.key --cert DB.crt --output uki.signed.efi uki.efi - - SAVE ARTIFACT /boot/efi/EFI/fedora/mmx64.efi MokManager.efi - SAVE ARTIFACT PK.key PK.key AS LOCAL build/PK.key - SAVE ARTIFACT PK.crt PK.crt AS LOCAL build/PK.crt - SAVE ARTIFACT PK.cer PK.cer AS LOCAL build/PK.cer - SAVE ARTIFACT KEK.key KEK.key AS LOCAL build/KEK.key - SAVE ARTIFACT KEK.crt KEK.crt AS LOCAL build/KEK.crt - SAVE ARTIFACT KEK.cer KEK.cer AS LOCAL build/KEK.cer - SAVE ARTIFACT DB.key DB.key AS LOCAL build/DB.key - SAVE ARTIFACT DB.crt DB.crt AS LOCAL build/DB.crt - SAVE ARTIFACT DB.cer DB.cer AS LOCAL build/DB.cer - SAVE ARTIFACT uki.signed.efi uki.efi AS LOCAL build/$ISO_NAME.signed-$KVERSION.efi - -# This target will prepare a disk.img ready with the uki artifact on it for qemu. Just attach it to qemu and mark you vm to boot from that disk -# here we take advantage of the uefi fallback method, which will load an efi binary in /EFI/BOOT/BOOTX64.efi if there is nothing -# else that it can boot from :D Just make sure to have your disk.img set as boot device in qemu. -prepare-uki-disk-image: - FROM +uki-tools-image - ARG SIGNED_EFI=false - IF [ "$SIGNED_EFI" = "true" ] - COPY +uki-signed/uki.efi . - COPY +uki-signed/PK.key . - COPY +uki-signed/PK.crt . - COPY +uki-signed/PK.cer . - COPY +uki-signed/KEK.key . - COPY +uki-signed/KEK.crt . - COPY +uki-signed/KEK.cer . - COPY +uki-signed/DB.key . - COPY +uki-signed/DB.crt . - COPY +uki-signed/DB.cer . - COPY +uki-signed/MokManager.efi . - ELSE - COPY +uki/uki.efi . - END - RUN dd if=/dev/zero of=disk.img bs=1G count=1 - RUN mformat -i disk.img -F :: - RUN mmd -i disk.img ::/EFI - RUN mmd -i disk.img ::/EFI/BOOT - RUN mcopy -i disk.img uki.efi ::/EFI/BOOT/BOOTX64.efi - IF [ "$SIGNED_EFI" = "true" ] - RUN mcopy -i disk.img PK.key ::/EFI/BOOT/PK.key - RUN mcopy -i disk.img PK.crt ::/EFI/BOOT/PK.crt - RUN mcopy -i disk.img PK.cer ::/EFI/BOOT/PK.cer - RUN mcopy -i disk.img KEK.key ::/EFI/BOOT/KEK.key - RUN mcopy -i disk.img KEK.crt ::/EFI/BOOT/KEK.crt - RUN mcopy -i disk.img KEK.cer ::/EFI/BOOT/KEK.cer - RUN mcopy -i disk.img DB.key ::/EFI/BOOT/DB.key - RUN mcopy -i disk.img DB.crt ::/EFI/BOOT/DB.crt - RUN mcopy -i disk.img DB.cer ::/EFI/BOOT/DB.cer - RUN mcopy -i disk.img MokManager.efi ::/EFI/BOOT/mmx64.efi - END - RUN mdir -i disk.img ::/EFI/BOOT - SAVE ARTIFACT disk.img AS LOCAL build/disk.img - + --add-section .osrel=Osrelease --set-section-flags .osrel=data,readonly \ + --add-section .cmdline=Cmdline --set-section-flags .cmdline=data,readonly \ + --add-section .initrd=Initrd --set-section-flags .initrd=data,readonly \ + --add-section .uname=Uname --set-section-flags .uname=data,readonly \ + --add-section .linux=Kernel --set-section-flags .linux=code,readonly \ + uki.unsigned.efi \ + --change-section-vma .osrel=0x17000 \ + --change-section-vma .cmdline=0x18000 \ + --change-section-vma .initrd=0x19000 \ + --change-section-vma .uname=0x5a0ed000 \ + --change-section-vma .linux=0x5a0ee000 + # example with ukify + measure + #RUN /usr/lib/systemd/ukify Kernel Initrd \ + # --cmdline Cmdline \ + # --os-release Osrelease \ + # --uname Uname \ + # --stub /usr/lib/systemd/boot/efi/linuxx64.efi.stub \ + # --secureboot-private-key DB.key \ + # --secureboot-certificate DB.crt \ + # --sign-kernel \ + # --pcr-private-key private.pem \ + # --pcr-public-key public.pem \ + # --measure \ + # --output $ISO_NAME.signed.efi + RUN sbsign --key DB.key --cert DB.crt --output systemd-bootx64.signed.efi /usr/lib/systemd/boot/efi/systemd-bootx64.efi + RUN sbsign --key DB.key --cert DB.crt --output uki.signed.efi uki.unsigned.efi + SAVE ARTIFACT PK.der PK.der + SAVE ARTIFACT KEK.der KEK.der + SAVE ARTIFACT DB.der DB.der + SAVE ARTIFACT systemd-bootx64.signed.efi systemd-bootx64.efi + SAVE ARTIFACT uki.signed.efi uki.signed.efi + SAVE ARTIFACT uki.unsigned.efi uki.unsigned.efi ### ### Artifacts targets (ISO, netboot, ARM) @@ -642,16 +601,39 @@ iso-uki: ARG OSBUILDER_IMAGE FROM $OSBUILDER_IMAGE WORKDIR /build - COPY +uki/uki.efi /build/uki.efi + COPY +uki/uki.signed.efi . + COPY +uki/PK.der . + COPY +uki/KEK.der . + COPY +uki/DB.der . + COPY +uki/systemd-bootx64.efi . + # Set the name for kairos manually as otherwise it picks it from the os-release automatically + RUN printf "title Kairos ${FLAVOR} ${VERSION}\nefi /EFI/kairos/kairos.efi" > kairos.conf + RUN printf "default kairos.conf" > loader.conf RUN mkdir -p /build/efi - # TODO: Create the img size based ont eh actual efi size! + # TODO: Create the img size based on the actual efi size! RUN dd if=/dev/zero of=/build/efi/efiboot.img bs=1G count=1 - RUN mkfs.msdos -F 32 -n 'EFIBOOTISO' /build/efi/efiboot.img + RUN mkfs.msdos -F 32 /build/efi/efiboot.img RUN mmd -i /build/efi/efiboot.img ::EFI RUN mmd -i /build/efi/efiboot.img ::EFI/BOOT + RUN mmd -i /build/efi/efiboot.img ::EFI/kairos + RUN mmd -i /build/efi/efiboot.img ::EFI/tools + RUN mmd -i /build/efi/efiboot.img ::loader + RUN mmd -i /build/efi/efiboot.img ::loader/entries + RUN mmd -i /build/efi/efiboot.img ::loader/keys + RUN mmd -i /build/efi/efiboot.img ::loader/keys/kairos + # Copy keys + RUN mcopy -i /build/efi/efiboot.img /build/PK.der ::loader/keys/kairos/PK.der + RUN mcopy -i /build/efi/efiboot.img /build/KEK.der ::loader/keys/kairos/KEK.der + RUN mcopy -i /build/efi/efiboot.img /build/DB.der ::loader/keys/kairos/DB.der + # Copy kairos efi. This dir would make system-boot autosearch and add to entries automatically /EFI/Linux/ + # but here we do it by using systemd-boot as fallback so it sets the proper efivars + RUN mcopy -i /build/efi/efiboot.img /build/kairos.conf ::loader/entries/kairos.conf + RUN mcopy -i /build/efi/efiboot.img /build/uki.signed.efi ::EFI/kairos/kairos.EFI + # systemd-boot as bootloader + RUN mcopy -i /build/efi/efiboot.img /build/loader.conf ::loader/loader.conf # TODO: TARGETARCH should change the output name to BOOTAA64.EFI in arm64! - RUN mcopy -i /build/efi/efiboot.img /build/uki.efi ::EFI/BOOT/BOOTX64.EFI - RUN xorriso -as mkisofs -V 'EFI_ISO_BOOT' -e efiboot.img -no-emul-boot -o /build/$ISO_NAME.iso /build/efi/ + RUN mcopy -i /build/efi/efiboot.img /build/systemd-bootx64.efi ::EFI/BOOT/BOOTX64.EFI + RUN xorriso -as mkisofs -V 'UKI_ISO_INSTALL' -e efiboot.img -no-emul-boot -o /build/$ISO_NAME.iso /build/efi/ SAVE ARTIFACT /build/$ISO_NAME.iso kairos.iso AS LOCAL build/$ISO_NAME.iso # This target builds an iso using a remote docker image as rootfs instead of building the whole rootfs diff --git a/tests/assets/efivars.fd b/tests/assets/efivars.fd new file mode 100644 index 00000000..1f99259c Binary files /dev/null and b/tests/assets/efivars.fd differ diff --git a/tests/assets/efivars.json b/tests/assets/efivars.json new file mode 100644 index 00000000..cc437c1f --- /dev/null +++ b/tests/assets/efivars.json @@ -0,0 +1,165 @@ +{ + "version": 2, + "variables": [ + { + "name": "CustomMode", + "guid": "c076ec0c-7028-4399-a072-71ee5c448b9f", + "attr": 3, + "data": "00" + }, + { + "name": "KEK", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 39, + "data": "a159c0a5e494a74a87b5ab155c2bf072d003000000000000b4030000a3a8baa01d04a848bc87c36d121b5e3d308203a030820288a003020102020900fef588e8f396c0f1300d06092a864886f70d01010b05003051312b302906035504031322526564204861742053656375726520426f6f742028504b2f4b454b206b65792031293122302006092a864886f70d0109011613736563616c657274407265646861742e636f6d301e170d3134313033313131313533375a170d3337313032353131313533375a3051312b302906035504031322526564204861742053656375726520426f6f742028504b2f4b454b206b65792031293122302006092a864886f70d0109011613736563616c657274407265646861742e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100901f847b8dbceb9726826d88ab8ac98c6870f9df4b07b237830b02c86768309ee3f0f0994ab85957c641f6388bfe664c49e93737922e98011e5b1450e6a88d250df586e6ab30cb4016ea8d8b1686704337f2cec091df71148e990e89b64c6d241e8ce42f4f25d0ba06f8c6e8191876731d816da8d805cf3ac87b28c836a3160d298c999a68dcabc04d8dbf5abb2ba9394b04971cf936bbc53a8604aeafd4827be0abde490568fcf6ae681a6c904d57193c646603f6c7529bf794cf936aa168c9aacf996bbcaa5e08e7391cf7f80fba067ef1cbe876ddfe22daad3a5e5b34eab3c9e04d04297eb860b905efb5d91758561660b93032f0364ac3f2798d124070f30203010001a37b307930090603551d1304023000302c06096086480186f842010d041f161d4f70656e53534c2047656e657261746564204365727469666963617465301d0603551d0e041604143ce960e3ff19a10a7ba342f48d422eb4d59c72ec301f0603551d230418301680143ce960e3ff19a10a7ba342f48d422eb4d59c72ec300d06092a864886f70d01010b050003820101005c4d9288b4825f1dad8b11ecdf06a67aa52b9f37550c8d6e0500adb70c418969cfd665069b5178d2adc7bf9cdc05737fe71e3913b4eab6307d4075ab9c430bdfb0c21bbf30e0f4fec0db622198f6c5afde3b4f490ae61ef986b03f0dd6d44637db54745eff11c260c67058c51c6fecb2d86e6fc3bc338738a4f344649c343b28942678279f1617e83b690a25a973367e9e375cece83fdb91f912b33dcee7dd15c3ae8c0520619b95de9baffab15c1ce597e7c3341185f58a2726a47036ec0cf6833d90f736f3f9f315d49062be53b4afd349afeff473e87b76e4442a37ba81a4990c3a312471a0e4e4b71acb47e4aa22cfef756180e343b7485773113d789b69a159c0a5e494a74a87b5ab155c2bf0721806000000000000fc050000bd9afa775903324dbd6028f4e78f784b308205e8308203d0a003020102020a610ad188000000000003300d06092a864886f70d01010b0500308191310b3009060355040613025553311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e313b3039060355040313324d6963726f736f667420436f72706f726174696f6e205468697264205061727479204d61726b6574706c61636520526f6f74301e170d3131303632343230343132395a170d3236303632343230353132395a308180310b3009060355040613025553311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e312a3028060355040313214d6963726f736f667420436f72706f726174696f6e204b454b204341203230313130820122300d06092a864886f70d01010105000382010f003082010a0282010100c4e8b58abfad5726b026c3eae7fb577a44025d070dda4ae5742ae6b00fec6debec7fb9e35a63327c11174f0ee30ba73815938ec6f5e084b19a9b2ce7f5b791d609e1e2c004a8ac301cdf48f306509a64a7517fc8854f8f2086cefe2fe19fff82c0ede9cdcef4536a623a0b43b9e225fdfe05f9d4c414ab11e223898d70b7a41d4decaee59cfa16c2d7c1cbd4e8c42fe599ee248b03ec8df28beac34afb4311120b7eb547926cdce60489ebf53304eb10012a71e5f983133cff25092f687646ffba4fbedcad712a58aafb0ed2793de49b653bcc292a9ffc7259a2ebae92eff6351380c602ece45fcc9d76cdef6392c1af79408479877fe352a8e89d7b07698f150203010001a382014f3082014b301006092b06010401823715010403020100301d0603551d0e0416041462fc43cda03ea4cb6712d25bd955ac7bccb68a5f301906092b0601040182371402040c1e0a00530075006200430041300b0603551d0f040403020186300f0603551d130101ff040530030101ff301f0603551d2304183016801445665243e17e5811bfd64e9e2355083b3a226aa8305c0603551d1f045530533051a04fa04d864b687474703a2f2f63726c2e6d6963726f736f66742e636f6d2f706b692f63726c2f70726f64756374732f4d6963436f725468695061724d6172526f6f5f323031302d31302d30352e63726c306006082b0601050507010104543052305006082b060105050730028644687474703a2f2f7777772e6d6963726f736f66742e636f6d2f706b692f63657274732f4d6963436f725468695061724d6172526f6f5f323031302d31302d30352e637274300d06092a864886f70d01010b05000382020100d48488f514941802ca2a3cfb2a921c0cd7a0d1f1e85266a8eea2b5757a9000aa2da4765aea79b7b9376a517b1064f6e164f20267bef7a81b78bdbace8858640cd657c819a35f05d6dbc6d069ce484b32b7eb5dd230f5c0f5b8ba7807a32bfe9bdb345684ec82caae4125709c6be9fe900fd7961fe5e7941fb22a0c8d4bff2829107bf7d77ca5d176b905c879ed0f90929cc2fedf6f7e6c0f7bd4c145dd345196390fe55e56d8180596f407a642b3a077fd0819f27156cc9f8623a487cba6fd587ed4696715917e81f27f13e50d8b8a3c8784ebe3cebd43e5ad2d84938e6a2b5a7c44fa52aa81c82d1cbbe052df0011f89a3dc160b0e133b5a388d165190a1ae7ac7ca4c182874e38b12f0dc514876ffd8d2ebc39b6e7e6c3e0e4cd2784ef9442ef298b9046413b811b67d8f9435965cb0dbcfd00924ff4753ba7a924fc50414079e02d4f0a6a27766e52ed96697baf0ff78705d045c2ad5314811ffb3004aa373661da4a691b34d868edd602cf6c940cd3cf6c2279adb1f0bc03a24660a9c407c22182f1fdf2e8793260bfd8aca522144bcac1d84beb7d3f5735b2e64f75b4b060032253ae91791dd69b411f15865470b2de0d350f7cb03472ba97603bf079eba2b21c5da216b887c5e91bf6b597256f389fe391fa8a7998c3690eb7a31c200597f8ca14ae00d7c4f3c01410756b34a01bb59960f35cb0c5574e36d23284bf9ea159c0a5e494a74a87b5ab155c2bf0723b030000000000001f0300002a5e6db7549b374999d8c40484fa19343082030b308201f3a003020102021414495741824d2fd3a63689379cb28d5b30c4c6e5300d06092a864886f70d01010b050030153113301106035504030c0a4b6169726f73204b454b301e170d3233303932353139343834355a170d3333303932323139343834355a30153113301106035504030c0a4b6169726f73204b454b30820122300d06092a864886f70d01010105000382010f003082010a02820101009aa7265d45de931609eb249b586140207c27c54b3a5140ba2b620a947da635527371944d6781c06cd461d14003bb8dd60fbcbdd088863ea8aa03189d76fd42ace92a5f3472d0b4743636b42b5435c582dfadb5aba1b1af93d25978eaa0dcdc7eb1f6cd63521188159824990f9a5e3e58147c230eda31c39bed270fe9efbae37b86c4b39f05af4a2fae50e6d9e9f6929895bd7490756c72d692c1b7541a85f65fe23aa0409d7703ea14471ee9832a0c6b2bed5631b894bb6490f9b92f9257226186d375e48ce7a17242a8411f3ca009a1cf30dab7dea2fb5f1d31ddc7476824578fe15d09cf3ed09f7c7055e6bdba92a7b82a88c2c7dae2cf7c84ca5bcc32d1390203010001a3533051301d0603551d0e041604143cfaf12bea8be61f8d19039149893fb360b062b4301f0603551d230418301680143cfaf12bea8be61f8d19039149893fb360b062b4300f0603551d130101ff040530030101ff300d06092a864886f70d01010b0500038201010030b239aa6331e7405d3a4a5202321d3aa1b9d74a4cdfd3ac21be4865fa6594301295b4c151e83dec1ecee9ce7361324a5815af63ea1638e1f8d4fbab6441a31c733fca38c0caa4994f9882caba2c6b69880257b1dca019a9284df6c700b3108777359dfc243c511668a3203b5d094b291f178c9fe3e91c3864bc17442bad3e6c0ec1662b3d6f6a83a22028e8da718dd54b90c055cdd1a0a8670de923cdba3832efcfcdfef9ddc46471c8dd9fb1c9a7bdfd2acecd4e3faf7a0324c343d559ff87cf43f9262df2fd24dbbc778731d7076057fdb416d3271e1af543b7f5fc6aabe52db3b772fd58bc274c33ab2dddd467dc25c2da51c9ed75d3b45a6a0c254e7be1", + "time": "e707091913302d000000000000000000" + }, + { + "name": "PK", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 39, + "data": "a159c0a5e494a74a87b5ab155c2bf072d003000000000000b4030000a3a8baa01d04a848bc87c36d121b5e3d308203a030820288a003020102020900fef588e8f396c0f1300d06092a864886f70d01010b05003051312b302906035504031322526564204861742053656375726520426f6f742028504b2f4b454b206b65792031293122302006092a864886f70d0109011613736563616c657274407265646861742e636f6d301e170d3134313033313131313533375a170d3337313032353131313533375a3051312b302906035504031322526564204861742053656375726520426f6f742028504b2f4b454b206b65792031293122302006092a864886f70d0109011613736563616c657274407265646861742e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100901f847b8dbceb9726826d88ab8ac98c6870f9df4b07b237830b02c86768309ee3f0f0994ab85957c641f6388bfe664c49e93737922e98011e5b1450e6a88d250df586e6ab30cb4016ea8d8b1686704337f2cec091df71148e990e89b64c6d241e8ce42f4f25d0ba06f8c6e8191876731d816da8d805cf3ac87b28c836a3160d298c999a68dcabc04d8dbf5abb2ba9394b04971cf936bbc53a8604aeafd4827be0abde490568fcf6ae681a6c904d57193c646603f6c7529bf794cf936aa168c9aacf996bbcaa5e08e7391cf7f80fba067ef1cbe876ddfe22daad3a5e5b34eab3c9e04d04297eb860b905efb5d91758561660b93032f0364ac3f2798d124070f30203010001a37b307930090603551d1304023000302c06096086480186f842010d041f161d4f70656e53534c2047656e657261746564204365727469666963617465301d0603551d0e041604143ce960e3ff19a10a7ba342f48d422eb4d59c72ec301f0603551d230418301680143ce960e3ff19a10a7ba342f48d422eb4d59c72ec300d06092a864886f70d01010b050003820101005c4d9288b4825f1dad8b11ecdf06a67aa52b9f37550c8d6e0500adb70c418969cfd665069b5178d2adc7bf9cdc05737fe71e3913b4eab6307d4075ab9c430bdfb0c21bbf30e0f4fec0db622198f6c5afde3b4f490ae61ef986b03f0dd6d44637db54745eff11c260c67058c51c6fecb2d86e6fc3bc338738a4f344649c343b28942678279f1617e83b690a25a973367e9e375cece83fdb91f912b33dcee7dd15c3ae8c0520619b95de9baffab15c1ce597e7c3341185f58a2726a47036ec0cf6833d90f736f3f9f315d49062be53b4afd349afeff473e87b76e4442a37ba81a4990c3a312471a0e4e4b71acb47e4aa22cfef756180e343b7485773113d789b69", + "time": "de070a1f0b0f25000000000000000000" + }, + { + "name": "SecureBootEnable", + "guid": "f0a30bc7-af08-4556-99c4-001009c93a44", + "attr": 3, + "data": "01" + }, + { + "name": "db", + "guid": "d719b2cb-3d3a-4596-a3bc-dad00e67656f", + "attr": 39, + "data": "a159c0a5e494a74a87b5ab155c2bf0720706000000000000eb050000bd9afa775903324dbd6028f4e78f784b308205d7308203bfa003020102020a61077656000000000008300d06092a864886f70d01010b0500308188310b3009060355040613025553311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e31323030060355040313294d6963726f736f667420526f6f7420436572746966696361746520417574686f726974792032303130301e170d3131313031393138343134325a170d3236313031393138353134325a308184310b3009060355040613025553311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e312e302c060355040313254d6963726f736f66742057696e646f77732050726f64756374696f6e20504341203230313130820122300d06092a864886f70d01010105000382010f003082010a0282010100dd0cbba2e42e09e3e7c5f79669bc0021bd693333efad04cb5480ee0683bbc52084d9f7d28bf338b0aba4ad2d7c627905ffe34a3f04352070e3c4e76be09cc03675e98a31dd8d70e5dc37b5744696285b8760232cbfdc47a567f751279e72eb07a6c9b91e3b53357ce5d3ec27b9871cfeb9c923096fa84691c16e963c41d3cba33f5d026a4dec691f25285c36fffd43150a94e019b4cfdfc212e2c25b27ee2778308b5b2a096b22895360162cc0681d53baec49f39d618c85680973445d7da2542bdd79f715cf355d6c1c2b5ccebc9c238b6f6eb526d93613c34fd627aeb9323b41922ce1c7cd77e8aa544ef75c0b048765b44318a8b2e06d1977ec5a24fa48030203010001a38201433082013f301006092b06010401823715010403020100301d0603551d0e04160414a92902398e16c49778cd90f99e4f9ae17c55af53301906092b0601040182371402040c1e0a00530075006200430041300b0603551d0f040403020186300f0603551d130101ff040530030101ff301f0603551d23041830168014d5f656cb8fe8a25c6268d13d94905bd7ce9a18c430560603551d1f044f304d304ba049a0478645687474703a2f2f63726c2e6d6963726f736f66742e636f6d2f706b692f63726c2f70726f64756374732f4d6963526f6f4365724175745f323031302d30362d32332e63726c305a06082b06010505070101044e304c304a06082b06010505073002863e687474703a2f2f7777772e6d6963726f736f66742e636f6d2f706b692f63657274732f4d6963526f6f4365724175745f323031302d30362d32332e637274300d06092a864886f70d01010b0500038202010014fc7c7151a579c26eb2ef393ebc3c520f6e2b3f101373fea868d048a6344d8a960526ee3146906179d6ff382e456bf4c0e528b8da1d8f8adb09d71ac74c0a36666a8cec1bd70490a81817a49bb9e240323676c4c15ac6bfe404c0ea16d3acc368ef62acdd546c503058a6eb7cfe94a74e8ef4ec7c867357c2522173345af3a38a56c804da0709edf88be3cef47e8eaef0f60b8a08fb3fc91d727f53b8ebbe63e0e33d3165b081e5f2accd16a49f3da8b19bc242d090845f541dff89eaba1d47906fb0734e419f409f5fe5a12ab21191738a2128f0cede73395f3eab5c60ecdf0310a8d309e9f4f69685b67f51886647198da2b0123d812a680577bb914c627bb6c107c7ba7a8734030e4b627a99e9cafcce4a37c92da4577c1cfe3ddcb80f5afad6c4b30285023aeab3d96ee4692137de81d1f675190567d393575e291b39c8ee2de1cde445735bd0d2ce7aab1619824658d05e9d81b367af6c35f2bce53f24e235a20a7506f6185699d4782cd1051bebd088019daa10f105dfba7e2c63b7069b2321c4f9786ce2581706362b911203cca4d9f22dbaf9949d40ed1845f1ce8a5c6b3eab03d370182a0a6ae05f47d1d5630a32f2afd7361f2a705ae5425908714b57ba7e8381f0213cf41cc1c5b990930e88459386e9b12099be98cbc595a45d62d6a0630820bd7510777d3df345b99f979fcb57806f33a904cf77a4621c597ea159c0a5e494a74a87b5ab155c2bf072400600000000000024060000bd9afa775903324dbd6028f4e78f784b30820610308203f8a003020102020a6108d3c4000000000004300d06092a864886f70d01010b0500308191310b3009060355040613025553311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e313b3039060355040313324d6963726f736f667420436f72706f726174696f6e205468697264205061727479204d61726b6574706c61636520526f6f74301e170d3131303632373231323234355a170d3236303632373231333234355a308181310b3009060355040613025553311330110603550408130a57617368696e67746f6e3110300e060355040713075265646d6f6e64311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e312b3029060355040313224d6963726f736f667420436f72706f726174696f6e2055454649204341203230313130820122300d06092a864886f70d01010105000382010f003082010a0282010100a5086c4cc745096a4b0ca4c0877f06750c43015464e0167f07ed927d0bb273bf0c0ac64a4561a0c5162d96d3f52ba0fb4d499b4180903cb954fde6bcd19dc4a4188a7f418a5c59836832bb8c47c9ee71bc214f9a8a7cff443f8d8f32b22648ae75b5eec94c1e4a197ee4829a1d78774d0cb0bdf60fd316d3bcfa2ba551385df5fbbadb7802dbffec0a1b96d583b81913e9b6c07b407be11f2827c9faef565e1ce67e947ec0f044b27939e5dab2628b4dbf3870e2682414c933a40837d558695ed37cedc1045308e74eb02a876308616f631559eab22b79d70c61678a5bfd5ead877fba86674f71581222042222ce8bef547100ce503558769508ee6ab1a201d50203010001a382017630820172301206092b060104018237150104050203010001302306092b060104018237150204160414f8c16bb77f77534af325371d4ea1267b0f207080301d0603551d0e0416041413adbf4309bd82709c8cd54f316ed522988a1bd4301906092b0601040182371402040c1e0a00530075006200430041300b0603551d0f040403020186300f0603551d130101ff040530030101ff301f0603551d2304183016801445665243e17e5811bfd64e9e2355083b3a226aa8305c0603551d1f045530533051a04fa04d864b687474703a2f2f63726c2e6d6963726f736f66742e636f6d2f706b692f63726c2f70726f64756374732f4d6963436f725468695061724d6172526f6f5f323031302d31302d30352e63726c306006082b0601050507010104543052305006082b060105050730028644687474703a2f2f7777772e6d6963726f736f66742e636f6d2f706b692f63657274732f4d6963436f725468695061724d6172526f6f5f323031302d31302d30352e637274300d06092a864886f70d01010b05000382020100350842ff30cccef7760cad1068583529463276277cef124127421b4aaa6d813848591355f3e95834a6160b82aa5dad82da808341068fb41df203b9f31a5d1bf15090f9b3558442281c20bdb2ae5114c5c0ac9795211c90db0ffc779e95739188cabdbd52b905500ddf579ea061ed0de56d25d9400f1740c8cea34ac24daf9a121d08548fbdc7bcb92b3d492b1f32fc6a21694f9bc87e4234fc3606178b8f2040c0b39a257527cdc903a3f65dd1e736547ab950b5d312d107bfbb74dfdc1e8f80d5ed18f42f14166b2fde668cb023e5c784d8edeac13382ad564b182df1689507cdcff072f0aebbdd8685982c214c332bf00f4af06887b592553275a16a826a3ca32511a4edadd704aecbd84059a084d1954c6291221a741d8c3d470e44a6e4b09b3435b1fab653a82c81eca40571c89db8bae81b4466e447540e8e567fb39f1698b286d0683e9023b52f5e8f50858dc68d825f41a1f42e0de099d26c75e4b669b52186fa07d1f6e24dd1daad2c77531e253237c76c52729586b0f135616a19f5b23b815056a6322dfea289f94286271855a182ca5a9bf830985414a64796252fc826e441941a5c023fe596e3855b3c3e3fbb47167255e22522b1d97be703062aa3f71e9046c3000dd61989e30e352762037115a6efd027a0a0593760f83894b8e07870f8ba4c868794f6e0ae0245ee65c2b6a37e69167507929bf5a6bc598358a159c0a5e494a74a87b5ab155c2bf07239030000000000001d0300002a5e6db7549b374999d8c40484fa193430820309308201f1a003020102021443c11ff901e9ea62d85d7bd7f3ff58b0a24320d6300d06092a864886f70d01010b050030143112301006035504030c094b6169726f73204442301e170d3233303932353139343835345a170d3333303932323139343835345a30143112301006035504030c094b6169726f7320444230820122300d06092a864886f70d01010105000382010f003082010a0282010100ef28987a3abfac0df7845c780f6a60f296c27d9169036af5086809a5a3b0d1e9989bda5ee8f98785f4fe9a27d751aa37982f618ed07e703fcb40d96eea0478c7a50cb3773afa2fb2d4f32576c3bf176bd2d26373ef9f4111ac223b8c746e8a6bfa83c94afa643f95148d8bc9f02779ab938de2b0447824fd77c13d9c6f6e1f75d0a103c0bf3a3d7a1867cc00261d2df98b685297aad4320c29e92db808a7066f0975a4dbe8539dbc5b4c6bd6160e6b36daffead942db86aac71461401b38b13584ea7f5161a6b3f9b47b34c1b15910d51c909fa7161ab295a53cda68dfb57b96a2c58c9773dfd0cd8e51a9de2a8ac4e6c1806c1dd795857a778a12645a74f3af0203010001a3533051301d0603551d0e04160414d4c712757e53809fc57088c8f923709bab2ce0cc301f0603551d23041830168014d4c712757e53809fc57088c8f923709bab2ce0cc300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000382010100ccee42139063121c2ad39d1bc6aa950d81985d768b1d0b130437891929c99e080e0f3e28e5a2828818ce02f35e4f8ea668701e83b8c9e1e370e417a2aaed8b4284c5402fde085b3a7eb61104d09ec0f31ece64fe8be62a66f73f4597e04d8fbae12471007bdf26e7a5537a404b681601e83b81065ad0a4c91b46569d42f0cbea4070ddb2724cf934e67b1e5d8f3d30941b2873b88828669d5db38c5de8b986b2cb8c641ea987284076f86892b61eb094fd053f2d086822aa3519592a46f20241a095c2d8a1e7e6213bd01e15fcb20205adb43ee707eeb0e06894c968a389e61a79d52e9d09402dde9ae03ec0f4b31fb8d8bbcd38ba25168688f291f9c8939e85", + "time": "e7070919133036000000000000000000" + }, + { + "name": "dbx", + "guid": "d719b2cb-3d3a-4596-a3bc-dad00e67656f", + "attr": 39, + "data": "2616c4c14c509240aca941f936934328ac4500000000000030000000bd9afa775903324dbd6028f4e78f784b80b4d96931bf0d02fd91a61e19d14f1da452e66db2408ca8604d411f92659f0abd9afa775903324dbd6028f4e78f784bf52f83a3fa9cfbd6920f722824dbe4034534d25b8507246b3b957dac6e1bce7abd9afa775903324dbd6028f4e78f784bc5d9d8a186e2c82d09afaa2a6f7f2e73870d3e64f72c4e08ef67796a840f0fbdbd9afa775903324dbd6028f4e78f784b1aec84b84b6c65a51220a9be7181965230210d62d6d33c48999c6b295a2b0a06bd9afa775903324dbd6028f4e78f784bc3a99a460da464a057c3586d83cef5f4ae08b7103979ed8932742df0ed530c66bd9afa775903324dbd6028f4e78f784b58fb941aef95a25943b3fb5f2510a0df3fe44c58c95e0ab80487297568ab9771bd9afa775903324dbd6028f4e78f784b5391c3a2fb112102a6aa1edc25ae77e19f5d6f09cd09eeb2509922bfcd5992eabd9afa775903324dbd6028f4e78f784bd626157e1d6a718bc124ab8da27cbb65072ca03a7b6b257dbdcbbd60f65ef3d1bd9afa775903324dbd6028f4e78f784bd063ec28f67eba53f1642dbf7dff33c6a32add869f6013fe162e2c32f1cbe56dbd9afa775903324dbd6028f4e78f784b29c6eb52b43c3aa18b2cd8ed6ea8607cef3cfae1bafe1165755cf2e614844a44bd9afa775903324dbd6028f4e78f784b90fbe70e69d633408d3e170c6832dbb2d209e0272527dfb63d49d29572a6f44cbd9afa775903324dbd6028f4e78f784b106faceacfecfd4e303b74f480a08098e2d0802b936f8ec774ce21f31686689cbd9afa775903324dbd6028f4e78f784b174e3a0b5b43c6a607bbd3404f05341e3dcf396267ce94f8b50e2e23a9da920cbd9afa775903324dbd6028f4e78f784b2b99cf26422e92fe365fbf4bc30d27086c9ee14b7a6fff44fb2f6b9001699939bd9afa775903324dbd6028f4e78f784b2e70916786a6f773511fa7181fab0f1d70b557c6322ea923b2a8d3b92b51af7dbd9afa775903324dbd6028f4e78f784b3fce9b9fdf3ef09d5452b0f95ee481c2b7f06d743a737971558e70136ace3e73bd9afa775903324dbd6028f4e78f784b47cc086127e2069a86e03a6bef2cd410f8c55a6d6bdb362168c31b2ce32a5adfbd9afa775903324dbd6028f4e78f784b71f2906fd222497e54a34662ab2497fcc81020770ff51368e9e3d9bfcbfd6375bd9afa775903324dbd6028f4e78f784b82db3bceb4f60843ce9d97c3d187cd9b5941cd3de8100e586f2bda5637575f67bd9afa775903324dbd6028f4e78f784b8ad64859f195b5f58dafaa940b6a6167acd67a886e8f469364177221c55945b9bd9afa775903324dbd6028f4e78f784b8d8ea289cfe70a1c07ab7365cb28ee51edd33cf2506de888fbadd60ebf80481cbd9afa775903324dbd6028f4e78f784baeebae3151271273ed95aa2e671139ed31a98567303a332298f83709a9d55aa1bd9afa775903324dbd6028f4e78f784bc409bdac4775add8db92aa22b5b718fb8c94a1462c1fe9a416b95d8a3388c2fcbd9afa775903324dbd6028f4e78f784bc617c1a8b1ee2a811c28b5a81b4c83d7c98b5b0c27281d610207ebe692c2967fbd9afa775903324dbd6028f4e78f784bc90f336617b8e7f983975413c997f10b73eb267fd8a10cb9e3bdbfc667abdb8bbd9afa775903324dbd6028f4e78f784b64575bd912789a2e14ad56f6341f52af6bf80cf94400785975e9f04e2d64d745bd9afa775903324dbd6028f4e78f784b45c7c8ae750acfbb48fc37527d6412dd644daed8913ccd8a24c94d856967df8ebd9afa775903324dbd6028f4e78f784b81d8fb4c9e2e7a8225656b4b8273b7cba4b03ef2e9eb20e0a0291624eca1ba86bd9afa775903324dbd6028f4e78f784bb92af298dc08049b78c77492d6551b710cd72aada3d77be54609e43278ef6e4dbd9afa775903324dbd6028f4e78f784be19dae83c02e6f281358d4ebd11d7723b4f5ea0e357907d5443decc5f93c1e9dbd9afa775903324dbd6028f4e78f784b39dbc2288ef44b5f95332cb777e31103e840dba680634aa806f5c9b100061802bd9afa775903324dbd6028f4e78f784b32f5940ca29dd812a2c145e6fc89646628ffcc7c7a42cae512337d8d29c40bbdbd9afa775903324dbd6028f4e78f784b10d45fcba396aef3153ee8f6ecae58afe8476a280a2026fc71f6217dcf49ba2fbd9afa775903324dbd6028f4e78f784b4b8668a5d465bcdd9000aa8dfcff42044fcbd0aece32fc7011a83e9160e89f09bd9afa775903324dbd6028f4e78f784b89f3d1f6e485c334cd059d0995e3cdfdc00571b1849854847a44dc5548e2dcfbbd9afa775903324dbd6028f4e78f784bc9ec350406f26e559affb4030de2ebde5435054c35a998605b8fcf04972d8d55bd9afa775903324dbd6028f4e78f784bb3e506340fbf6b5786973393079f24b66ba46507e35e911db0362a2acde97049bd9afa775903324dbd6028f4e78f784b9f1863ed5717c394b42ef10a6607b144a65ba11fb6579df94b8eb2f0c4cd60c1bd9afa775903324dbd6028f4e78f784bdd59af56084406e38c63fbe0850f30a0cd1277462a2192590fb05bc259e61273bd9afa775903324dbd6028f4e78f784bdbaf9e056d3d5b38b68553304abc88827ebc00f80cb9c7e197cdbc5822cd316cbd9afa775903324dbd6028f4e78f784b65f3c0a01b8402d362b9722e98f75e5e991e6c186e934f7b2b2e6be6dec800ecbd9afa775903324dbd6028f4e78f784b5b248e913d71853d3da5aedd8d9a4bc57a917126573817fb5fcb2d86a2f1c886bd9afa775903324dbd6028f4e78f784b2679650fe341f2cf1ea883460b3556aaaf77a70d6b8dc484c9301d1b746cf7b5bd9afa775903324dbd6028f4e78f784bbb1dd16d530008636f232303a7a86f3dff969f848815c0574b12c2d787fec93fbd9afa775903324dbd6028f4e78f784b0ce02100f67c7ef85f4eed368f02bf7092380a3c23ca91fd7f19430d94b00c19bd9afa775903324dbd6028f4e78f784b95049f0e4137c790b0d2767195e56f73807d123adcf8f6e7bf2d4d991d305f89bd9afa775903324dbd6028f4e78f784b02e6216acaef6401401fa555ecbed940b1a5f2569aed92956137ae58482ef1b7bd9afa775903324dbd6028f4e78f784b6efefe0b5b01478b7b944c10d3a8aca2cca4208888e2059f8a06cb5824d7bab0bd9afa775903324dbd6028f4e78f784b9d00ae4cd47a41c783dc48f342c076c2c16f3413f4d2df50d181ca3bb5ad859dbd9afa775903324dbd6028f4e78f784bd8d4e6ddf6e42d74a6a536ea62fd1217e4290b145c9e5c3695a31b42efb5f5a4bd9afa775903324dbd6028f4e78f784bf277af4f9bdc918ae89fa35cc1b34e34984c04ae9765322c3cb049574d36509cbd9afa775903324dbd6028f4e78f784b0dc24c75eb1aef56b9f13ab9de60e2eca1c4510034e290bbb36cf60a549b234cbd9afa775903324dbd6028f4e78f784b835881f2a5572d7059b5c8635018552892e945626f115fc9ca07acf7bde857a4bd9afa775903324dbd6028f4e78f784bbadff5e4f0fea711701ca8fb22e4c43821e31e210cf52d1d4f74dd50f1d039bcbd9afa775903324dbd6028f4e78f784bc452ab846073df5ace25cca64d6b7a09d906308a1a65eb5240e3c4ebcaa9cc0cbd9afa775903324dbd6028f4e78f784bf1863ec8b7f43f94ad14fb0b8b4a69497a8c65ecbc2a55e0bb420e772b8cdc91bd9afa775903324dbd6028f4e78f784b7bc9cb5463ce0f011fb5085eb8ba77d1acd283c43f4a57603cc113f22cebc579bd9afa775903324dbd6028f4e78f784be800395dbe0e045781e8005178b4baf5a257f06e159121a67c595f6ae22506fdbd9afa775903324dbd6028f4e78f784b1cb4dccaf2c812cfa7b4938e1371fe2b96910fe407216fd95428672d6c7e7316bd9afa775903324dbd6028f4e78f784b3ece27cbb3ec4438cce523b927c4f05fdc5c593a3766db984c5e437a3ff6a16bbd9afa775903324dbd6028f4e78f784b68ee4632c7be1c66c83e89dd93eaee1294159abf45b4c2c72d7dc7499aa2a043bd9afa775903324dbd6028f4e78f784be24b315a551671483d8b9073b32de11b4de1eb2eab211afd2d9c319ff55e08d0bd9afa775903324dbd6028f4e78f784be7c20b3ab481ec885501eca5293781d84b5a1ac24f88266b5270e7ecb4aa2538bd9afa775903324dbd6028f4e78f784bdccc3ce1c00ee4b0b10487d372a0fa47f5c26f57a359be7b27801e144eacbac4bd9afa775903324dbd6028f4e78f784b0257ff710f2a16e489b37493c07604a7cda96129d8a8fd68d2b6af633904315dbd9afa775903324dbd6028f4e78f784b3a91f0f9e5287fa2994c7d930b2c1a5ee14ce8e1c8304ae495adc58cc4453c0cbd9afa775903324dbd6028f4e78f784b495300790e6c9bf2510daba59db3d57e9d2b85d7d7640434ec75baa3851c74e5bd9afa775903324dbd6028f4e78f784b81a8b2c9751aeb1faba7dbde5ee9691dc0eaee2a31c38b1491a8146756a6b770bd9afa775903324dbd6028f4e78f784b8e53efdc15f852cee5a6e92931bc42e6163cd30ff649cca7e87252c3a459960bbd9afa775903324dbd6028f4e78f784b992d359aa7a5f789d268b94c11b9485a6b1ce64362b0edb4441ccc187c39647bbd9afa775903324dbd6028f4e78f784b9fa4d5023fd43ecaff4200ba7e8d4353259d2b7e5e72b5096eff8027d66d1043bd9afa775903324dbd6028f4e78f784bd372c0d0f4fdc9f52e9e1f23fc56ee72414a17f350d0cea6c26a35a6c3217a13bd9afa775903324dbd6028f4e78f784b5c5805196a85e93789457017d4f9eb6828b97c41cb9ba6d3dc1fcc115f527a55bd9afa775903324dbd6028f4e78f784b03f64a29948a88beffdb035e0b09a7370ccf0cd9ce6bcf8e640c2107318fab87bd9afa775903324dbd6028f4e78f784b05d87e15713454616f5b0ed7849ab5c1712ab84f02349478ec2a38f970c01489bd9afa775903324dbd6028f4e78f784b06eb5badd26e4fae65f9a42358deef7c18e52cc05fbb7fc76776e69d1b982a14bd9afa775903324dbd6028f4e78f784b08bb2289e9e91b4d20ff3f1562516ab07e979b2c6cefe2ab70c6dfc1199f8da5bd9afa775903324dbd6028f4e78f784b0928f0408bf725e61d67d87138a8eebc52962d2847f16e3587163b160e41b6adbd9afa775903324dbd6028f4e78f784b09f98aa90f85198c0d73f89ba77e87ec6f596c491350fb8f8bba80a62fbb914bbd9afa775903324dbd6028f4e78f784b0a75ea0b1d70eaa4d3f374246db54fc7b43e7f596a353309b9c36b4fd975725ebd9afa775903324dbd6028f4e78f784b0c51d7906fc4931149765da88682426b2cfe9e6aa4f27253eab400111432e3a7bd9afa775903324dbd6028f4e78f784b0fa3a29ad05130d7fe5bf4d2596563cded1d874096aacc181069932a2e49519abd9afa775903324dbd6028f4e78f784b147730b42f11fe493fe902b6251e97cd2b6f34d36af59330f11d02a42f940d07bd9afa775903324dbd6028f4e78f784b148fe18f715a9fcfe1a444ce0fff7f85869eb422330dc04b314c0f295d6da79ebd9afa775903324dbd6028f4e78f784b1b909115a8d473e51328a87823bd621ce655dfae54fa2bfa72fdc0298611d6b8bd9afa775903324dbd6028f4e78f784b1d8b58c1fdb8da8b33ccee1e5f973af734d90ef317e33f5db1573c2ba088a80cbd9afa775903324dbd6028f4e78f784b1f179186efdf5ef2de018245ba0eae8134868601ba0d35ff3d9865c1537ced93bd9afa775903324dbd6028f4e78f784b270c84b29d86f16312b06aaae4ebb8dff8de7d080d825b8839ff1766274eff47bd9afa775903324dbd6028f4e78f784b29cca4544ea330d61591c784695c149c6b040022ac7b5b89cbd72800d10840eabd9afa775903324dbd6028f4e78f784b2b2298eaa26b9dc4a4558ae92e7bb0e4f85cf34bf848fdf636c0c11fbec49897bd9afa775903324dbd6028f4e78f784b2dcf8e8d817023d1e8e1451a3d68d6ec30d9bed94cbcb87f19ddc1cc0116ac1abd9afa775903324dbd6028f4e78f784b311a2ac55b50c09b30b3cc93b994a119153eeeac54ef892fc447bbbd96101aa1bd9afa775903324dbd6028f4e78f784b32ad3296829bc46dcfac5eddcb9dbf2c1eed5c11f83b2210cf9c6e60c798d4a7bd9afa775903324dbd6028f4e78f784b340da32b58331c8e2b561baf300ca9dfd6b91cd2270ee0e2a34958b1c6259e85bd9afa775903324dbd6028f4e78f784b362ed31d20b1e00392281231a96f0a0acfde02618953e695c9ef2eb0bac37550bd9afa775903324dbd6028f4e78f784b367a31e5838831ad2c074647886a6cdff217e6b1ba910bff85dc7a87ae9b5e98bd9afa775903324dbd6028f4e78f784b3765d769c05bf98b427b3511903b2137e8a49b6f859d0af159ed6a86786aa634bd9afa775903324dbd6028f4e78f784b386d695cdf2d4576e01bcaccf5e49e78da51af9955c0b8fa7606373b007994b3bd9afa775903324dbd6028f4e78f784b3a4f74beafae2b9383ad8215d233a6cf3d057fb3c7e213e897beef4255faee9dbd9afa775903324dbd6028f4e78f784b3ae76c45ca70e9180c1559981f42622dd251bca1fbe6b901c52ec11673b03514bd9afa775903324dbd6028f4e78f784b3be8e7eb348d35c1928f19c769846788991641d1f6cf09514ca10269934f7359bd9afa775903324dbd6028f4e78f784b3e3926f0b8a15ad5a14167bb647a843c3d4321e35dbc44dce8c837417f2d28b0bd9afa775903324dbd6028f4e78f784b400ac66d59b7b094a9e30b01a6bd013aff1d30570f83e7592f421dbe5ff4ba8fbd9afa775903324dbd6028f4e78f784b4185821f6dab5ba8347b78a22b5f9a0a7570ca5c93a74d478a793d83bac49805bd9afa775903324dbd6028f4e78f784b41d1eeb177c0324e17dd6557f384e532de0cf51a019a446b01efb351bc259d77bd9afa775903324dbd6028f4e78f784b45876b4dd861d45b3a94800774027a5db45a48b2a729410908b6412f8a87e95dbd9afa775903324dbd6028f4e78f784b4667bf250cd7c1a06b8474c613cdb1df648a7f58736fbf57d05d6f755dab67f4bd9afa775903324dbd6028f4e78f784b47ff1b63b140b6fc04ed79131331e651da5b2e2f170f5daef4153dc2fbc532b1bd9afa775903324dbd6028f4e78f784b57e6913afacc5222bd76cdaf31f8ed88895464255374ef097a82d7f59ad39596bd9afa775903324dbd6028f4e78f784b5890fa227121c76d90ed9e63c87e3a6533eea0f6f0a1a23f1fc445139bc6bcdfbd9afa775903324dbd6028f4e78f784b5d1e9acbbb4a7d024b6852df025970e2ced66ff622ee019cd0ed7fd841ccad02bd9afa775903324dbd6028f4e78f784b61cec4a377bf5902c0feaee37034bf97d5bc6e0615e23a1cdfbae6e3f5fb3cfdbd9afa775903324dbd6028f4e78f784b631f0857b41845362c90c6980b4b10c4b628e23dbe24b6e96c128ae3dcb0d5acbd9afa775903324dbd6028f4e78f784b65b2e7cc18d903c331df1152df73ca0dc932d29f17997481c56f3087b2dd3147bd9afa775903324dbd6028f4e78f784b66aa13a0edc219384d9c425d3927e6ed4a5d1940c5e7cd4dac88f5770103f2f1bd9afa775903324dbd6028f4e78f784b6873d2f61c29bd52e954eeff5977aa8367439997811a62ff212c948133c68d97bd9afa775903324dbd6028f4e78f784b6dbbead23e8c860cf8b47f74fbfca5204de3e28b881313bb1d1eccdc4747934ebd9afa775903324dbd6028f4e78f784b6dead13257dfc3ccc6a4b37016ba91755fe9e0ec1f415030942e5abc47f07c88bd9afa775903324dbd6028f4e78f784b70a1450af2ad395569ad0afeb1d9c125324ee90aec39c258880134d4892d51abbd9afa775903324dbd6028f4e78f784b72c26f827ceb92989798961bc6ae748d141e05d3ebcfb65d9041b266c920be82bd9afa775903324dbd6028f4e78f784b781764102188a8b4b173d4a8f5ec94d828647156097f99357a581e624b377509bd9afa775903324dbd6028f4e78f784b788383a4c733bb87d2bf51673dc73e92df15ab7d51dc715627ae77686d8d23bcbd9afa775903324dbd6028f4e78f784b78b4edcaabc8d9093e20e217802caeb4f09e23a3394c4acc6e87e8f35395310fbd9afa775903324dbd6028f4e78f784b7f49ccb309323b1c7ab11c93c955b8c744f0a2b75c311f495e18906070500027bd9afa775903324dbd6028f4e78f784b82acba48d5236ccff7659afc14594dee902bd6082ef1a30a0b9b508628cf34f4bd9afa775903324dbd6028f4e78f784b894d7839368f3298cc915ae8742ef330d7a26699f459478cf22c2b6bb2850166bd9afa775903324dbd6028f4e78f784b8c0349d708571ae5aa21c11363482332073297d868f29058916529efc520ef70bd9afa775903324dbd6028f4e78f784b8d93d60c691959651476e5dc464be12a85fa5280b6f524d4a1c3fcc9d048cfadbd9afa775903324dbd6028f4e78f784b9063f5fbc5e57ab6de6c9488146020e172b176d5ab57d4c89f0f600e17fe2de2bd9afa775903324dbd6028f4e78f784b91656aa4ef493b3824a0b7263248e4e2d657a5c8488d880cb65b01730932fb53bd9afa775903324dbd6028f4e78f784b91971c1497bf8e5bc68439acc48d63ebb8faabfd764dcbe82f3ba977cac8cf6abd9afa775903324dbd6028f4e78f784b947078f97c6196968c3ae99c9a5d58667e86882cf6c8c9d58967a496bb7af43cbd9afa775903324dbd6028f4e78f784b96e4509450d380dac362ff8e295589128a1f1ce55885d20d89c27ba2a9d00909bd9afa775903324dbd6028f4e78f784b9783b5ee4492e9e891c655f1f48035959dad453c0e623af0fe7bf2c0a57885e3bd9afa775903324dbd6028f4e78f784b97a51a094444620df38cd8c6512cac909a75fd437ae1e4d22929807661238127bd9afa775903324dbd6028f4e78f784b97a8c5ba11d61fefbb5d6a05da4e15ba472dc4c6cd4972fc1a035de321342fe4bd9afa775903324dbd6028f4e78f784b992820e6ec8c41daae4bd8ab48f58268e943a670d35ca5e2bdcd3e7c4c94a072bd9afa775903324dbd6028f4e78f784b9954a1a99d55e8b189ab1bca414b91f6a017191f6c40a86b6f3ef368dd860031bd9afa775903324dbd6028f4e78f784b9baf4f76d76bf5d6a897bfbd5f429ba14d04e08b48c3ee8d76930a828fff3891bd9afa775903324dbd6028f4e78f784b9c259fcb301d5fc7397ed5759963e0ef6b36e42057fd73046e6bd08b149f751cbd9afa775903324dbd6028f4e78f784b9dd2dcb72f5e741627f2e9e03ab18503a3403cf6a904a479a4db05d97e2250a9bd9afa775903324dbd6028f4e78f784b9ed33f0fbc180bc032f8909ca2c4ab3418edc33a45a50d2521a3b5876aa3ea2cbd9afa775903324dbd6028f4e78f784ba4d978b7c4bda15435d508f8b9592ec2a5adfb12ea7bad146a35ecb53094642fbd9afa775903324dbd6028f4e78f784ba924d3cad6da42b7399b96a095a06f18f6b1aba5b873b0d5f3a0ee2173b48b6cbd9afa775903324dbd6028f4e78f784bad3be589c0474e97de5bb2bf33534948b76bb80376dfdc58b1fed767b5a15bfcbd9afa775903324dbd6028f4e78f784bb8d6b5e7857b45830e017c7be3d856adeb97c7290eb0665a3d473a4beb51dcf3bd9afa775903324dbd6028f4e78f784bb93f0699598f8b20fa0dacc12cfcfc1f2568793f6e779e04795e6d7c22530f75bd9afa775903324dbd6028f4e78f784bbb01da0333bb639c7e1c806db0561dc98a5316f22fef1090fb8d0be46dae499abd9afa775903324dbd6028f4e78f784bbc75f910ff320f5cb5999e66bbd4034f4ae537a42fdfef35161c5348e366e216bd9afa775903324dbd6028f4e78f784bbdd01126e9d85710d3fe75af1cc1702a29f081b4f6fdf6a2b2135c0297a9cec5bd9afa775903324dbd6028f4e78f784bbe435df7cd28aa2a7c8db4fc8173475b77e5abf392f76b7c76fa3f698cb71a9abd9afa775903324dbd6028f4e78f784bbef7663be5ea4dbfd8686e24701e036f4c03fb7fcd67a6c566ed94ce09c44470bd9afa775903324dbd6028f4e78f784bc2469759c1947e14f4b65f72a9f5b3af8b6f6e727b68bb0d91385cbf42176a8abd9afa775903324dbd6028f4e78f784bc3505bf3ec10a51dace417c76b8bd10939a065d1f34e75b8a3065ee31cc69b96bd9afa775903324dbd6028f4e78f784bc42d11c70ccf5e8cf3fb91fdf21d884021ad836ca68adf2cbb7995c10bf588d4bd9afa775903324dbd6028f4e78f784bc69d64a5b839e41ba16742527e17056a18ce3c276fd26e34901a1bc7d0e32219bd9afa775903324dbd6028f4e78f784bcb340011afeb0d74c4a588b36ebaa441961608e8d2fa80dca8c13872c850796bbd9afa775903324dbd6028f4e78f784bcc8eec6eb9212cbf897a5ace7e8abeece1079f1a6def0a789591cb1547f1f084bd9afa775903324dbd6028f4e78f784bcf13a243c1cd2e3c8ceb7e70100387cecbfb830525bbf9d0b70c79adf3e84128bd9afa775903324dbd6028f4e78f784bd89a11d16c488dd4fbbc541d4b07faf8670d660994488fe54b1fbff2704e4288bd9afa775903324dbd6028f4e78f784bd9668ab52785086786c134b5e4bddbf72452813b6973229ab92aa1a54d201bf5bd9afa775903324dbd6028f4e78f784bda3560fd0c32b54c83d4f2ff869003d2089369acf2c89608f8afa7436bfa4655bd9afa775903324dbd6028f4e78f784bdf02aab48387a9e1d4c65228089cb6abe196c8f4b396c7e4bbc395de136977f6bd9afa775903324dbd6028f4e78f784bdf91ac85a94fcd0cfb8155bd7cbefaac14b8c5ee7397fe2cc85984459e2ea14ebd9afa775903324dbd6028f4e78f784be051b788ecbaeda53046c70e6af6058f95222c046157b8c4c1b9c2cfc65f46e5bd9afa775903324dbd6028f4e78f784be36dfc719d2114c2e39aea88849e2845ab326f6f7fe74e0e539b7e54d81f3631bd9afa775903324dbd6028f4e78f784be39891f48bbcc593b8ed86ce82ce666fc1145b9fcbfd2b07bad0a89bf4c7bfbfbd9afa775903324dbd6028f4e78f784be6856f137f79992dc94fa2f43297ec32d2d9a76f7be66114c6a13efc3bcdf5c8bd9afa775903324dbd6028f4e78f784beaff8c85c208ba4d5b6b8046f5d6081747d779bada7768e649d047ff9b1f660cbd9afa775903324dbd6028f4e78f784bee83a566496109a74f6ac6e410df00bb29a290e0021516ae3b8a23288e7e2e72bd9afa775903324dbd6028f4e78f784beed7e0eff2ed559e2a79ee361f9962af3b1e999131e30bb7fd07546fae0a7267bd9afa775903324dbd6028f4e78f784bf1b4f6513b0d544a688d13adc291efa8c59f420ca5dcb23e0b5a06fa7e0d083dbd9afa775903324dbd6028f4e78f784bf2a16d35b554694187a70d40ca682959f4f35c2ce0eab8fd64f7ac2ab9f5c24abd9afa775903324dbd6028f4e78f784bf31fd461c5e99510403fc97c1da2d8a9cbe270597d32badf8fd66b77495f8d94bd9afa775903324dbd6028f4e78f784bf48e6dd8718e953b60a24f2cbea60a9521deae67db25425b7d3ace3c517dd9b7bd9afa775903324dbd6028f4e78f784bc805603c4fa038776e42f263c604b49d96840322e1922d5606a9b0bbb5bffe6fbd9afa775903324dbd6028f4e78f784b1f16078cce009df62edb9e7170e66caae670bce71b8f92d38280c56aa372031dbd9afa775903324dbd6028f4e78f784b37a480374daf6202ce790c318a2bb8aa3797311261160a8e30558b7dea78c7a6bd9afa775903324dbd6028f4e78f784b408b8b3df5abb043521a493525023175ab1261b1de21064d6bf247ce142153b9bd9afa775903324dbd6028f4e78f784b540801dd345dc1c33ef431b35bf4c0e68bd319b577b9abe1a9cff1cbc39f548fbd9afa775903324dbd6028f4e78f784b040b3bc339e9b6f9acd828b88f3482a5c3f64e67e5a714ba1da8a70453b34af6bd9afa775903324dbd6028f4e78f784b1142a0cc7c9004dff64c5948484d6a7ec3514e176f5ca6bdeed7a093940b93ccbd9afa775903324dbd6028f4e78f784b288878f12e8b9c6ccbf601c73d5f4e985cac0ff3fcb0c24e4414912b3eb91f15bd9afa775903324dbd6028f4e78f784b2ea4cb6a1f1eb1d3dce82d54fde26ded243ba3e18de7c6d211902a594fe56788bd9afa775903324dbd6028f4e78f784b40d6cae02973789080cf4c3a9ad11b5a0a4d8bba4438ab96e276cc784454dee7bd9afa775903324dbd6028f4e78f784b4f0214fce4fa8897d0c80a46d6dab4124726d136fc2492efd01bfedfa3887a9cbd9afa775903324dbd6028f4e78f784b5c2afe34bd8a7aebbb439c251dfb6a424f00e535ac4df61ec19745b6f10e893abd9afa775903324dbd6028f4e78f784b99d7ada0d67e5233108dbd76702f4b168087cfc4ec65494d6ca8aba858febadabd9afa775903324dbd6028f4e78f784ba608a87f51bdf7532b4b80fa95eadfdf1bf8b0cbb58a7d3939c9f11c12e71c85bd9afa775903324dbd6028f4e78f784bbdd4086c019f5d388453c6d93475d39a576572baff75612c321b46a35a5329b1bd9afa775903324dbd6028f4e78f784bcb994b400590b66cbf55fc663555caf0d4f1ce267464d0452c2361e05ee1cd50bd9afa775903324dbd6028f4e78f784bd6ee8db782e36caffb4d9f8207900487de930aabcc1d196fa455fbfd6f37273dbd9afa775903324dbd6028f4e78f784bdda0121dcf167db1e2622d10f454701837ac6af304a03ec06b3027904988c56bbd9afa775903324dbd6028f4e78f784be42572afac720f5d4a1c7aaaf802f094daceb682f4e92783b2bb3fa00862af7fbd9afa775903324dbd6028f4e78f784be6236dc1ee074c077c7a1c9b3965947430847be125f7aeb71d91a128133aea7fbd9afa775903324dbd6028f4e78f784bef87be89a413657de8721498552cf9e0f3c1f71bc62dfa63b9f25bbc66e86494bd9afa775903324dbd6028f4e78f784bf5e892dd6ec4c2defa4a495c09219b621379b64da3d1b2e34adf4b5f1102bd39bd9afa775903324dbd6028f4e78f784bd4241190cd5a369d8c344c660e24f3027fb8e7064fab33770e93fa765ffb152ebd9afa775903324dbd6028f4e78f784b23142e14424fb3ff4efc75d00b63867727841aba5005149070ee2417df8ab799bd9afa775903324dbd6028f4e78f784b91721aa76266b5bb2f8009f1188510a36e54afd56e967387ea7d0b114d782089bd9afa775903324dbd6028f4e78f784bdc8aff7faa9d1a00a3e32eefbf899b3059cbb313a48b82fa9c8d931fd58fb69dbd9afa775903324dbd6028f4e78f784b9959ed4e05e548b59f219308a45563ea85bb224c1ad96dec0e96c0e71ffccd81bd9afa775903324dbd6028f4e78f784b47b31a1c7867644b2ee8093b2d5fbe21e21f77c1617a2c08812f57ace0850e9fbd9afa775903324dbd6028f4e78f784bfabc379df395e6f52472b44fa5082f9f0e0da480f05198c66814b7055b03f446bd9afa775903324dbd6028f4e78f784be37ff3fc0eff20bfc1c060a4bf56885e1efd55a8e9ce3c5f4869444cacffad0bbd9afa775903324dbd6028f4e78f784b4cdae3920a512c9c052a8b4aba9096969b0a0197b614031e4c64a5d898cb09b9bd9afa775903324dbd6028f4e78f784b5b89f1aa2435a03d18d9b203d17fb4fba4f8f5076cf1f9b8d6d9b826222235c1bd9afa775903324dbd6028f4e78f784b007f4c95125713b112093e21663e2d23e3c1ae9ce4b5de0d58a297332336a2d8bd9afa775903324dbd6028f4e78f784be060da09561ae00dcfb1769d6e8e846868a1e99a54b14aa5d0689f2840cec6dfbd9afa775903324dbd6028f4e78f784b48f4584de1c5ec650c25e6c623635ce101bd82617fc400d4150f0aee2355b4cabd9afa775903324dbd6028f4e78f784baf79b14064601bc0987d4747af1e914a228c05d622ceda03b7a4f67014fee767bd9afa775903324dbd6028f4e78f784bc55be4a2a6ac574a9d46f1e1c54cac29d29dcd7b9040389e7157bb32c4591c4cbd9afa775903324dbd6028f4e78f784be9d873cbcede3634e0a4b3644b51e1c8a0a048272992c738513ebc96cd3e3360bd9afa775903324dbd6028f4e78f784b66d0803e2550d9e790829ae1b5f81547cc9bfbe69b51817068ecb5dabb7a89fcbd9afa775903324dbd6028f4e78f784b284153e7d04a9f187e5c3dbfe17b2672ad2fbdd119f27bec789417b7919853ecbd9afa775903324dbd6028f4e78f784bedd2cb55726e10abedec9de8ca5ded289ad793ab3b6919d163c875fec1209cd5bd9afa775903324dbd6028f4e78f784b90aec5c4995674a849c1d1384463f3b02b5aa625a5c320fc4fe7d9bb58a62398bd9afa775903324dbd6028f4e78f784bca65a9b2915d9a055a407bc0698936349a04e3db691e178419fba701aad8de55bd9afa775903324dbd6028f4e78f784b1788d84aa61ede6f2e96cfc900ad1cab1c5be86537f27212e8c291d6ade3b1e9bd9afa775903324dbd6028f4e78f784b6a0e824654b7479152058cf738a378e629483874b6dbd67e0d8c3327b2fcac64bd9afa775903324dbd6028f4e78f784b1eaed62c4abcb2524643e1723f6aadcc31a74af4d2285d3b13880cc44c22dec5bd9afa775903324dbd6028f4e78f784b21f27d89f2e77dee7cd4336e3a3ade362a2aae9fb2efe2079491a518f3d51fedbd9afa775903324dbd6028f4e78f784b250ae0ba860d6d46894491d630d58b1ca008f695c92ce2084a295486f71f985bbd9afa775903324dbd6028f4e78f784b399f9da6cf5a87839637b55f62bb2cc6a93fa5af7fe7ad76b4af0fb320c98127bd9afa775903324dbd6028f4e78f784b3b30c3e6a923cbb7cf65b539025f12b1c810d74480f25cbfcb9a7bfd633f06edbd9afa775903324dbd6028f4e78f784b3fe9f8d11edca3fc1899100484de4cc2c626abb38b73985a441b7c3a0d39ca54bd9afa775903324dbd6028f4e78f784b459457c48e1b450d8f22858ffb392fca78bb6f4da837862889ab798bdcbdf08fbd9afa775903324dbd6028f4e78f784b5a184e740657e218d635168286f0f70bb5672e4edb78717550c70686c232ea5bbd9afa775903324dbd6028f4e78f784b5e2bb7bc8b16e0b9ddff75606668e69d76af1219c17180ef0a5b9b383f00b995bd9afa775903324dbd6028f4e78f784b7fddfe06c44dc4302da54577353c18fdbe11b41cb3e6064ec1c116ee102fe080bd9afa775903324dbd6028f4e78f784b9141ea1a4e6bf1f4d72c28a1d0d124a928d5a7d36b14fc7e7e53ef442360ff99bd9afa775903324dbd6028f4e78f784b93f5233e9970a7db1e4c9aa2de2404636728e7c66c03f2bbe74b18b20a93ba96bd9afa775903324dbd6028f4e78f784bae1dca8aab7c4bdd21c5aa19a323f597bd1850445d76695cb2910cccb5f163b8bd9afa775903324dbd6028f4e78f784bbfcaa41445f20b54aea650d03d7c39b77cd82a7a14824dc55aa587c4c0f742a3bd9afa775903324dbd6028f4e78f784bc3297e35c3a9efc4c051706aab77d29a26e62d9a38de256dffeb77a0eec8666abd9afa775903324dbd6028f4e78f784bc875ae8a8db5441a577172869a4ec6e71dace7a875f42a2fbba4b52f293499debd9afa775903324dbd6028f4e78f784bdb1e5c6152a28d3eb6b1afeaad4974f3654ac6fbbe769d870abb74ede632b9e5bd9afa775903324dbd6028f4e78f784bdbb424cb8ad35ee68546092645c4689d6027a97fedf3c5af842b9572f1276997bd9afa775903324dbd6028f4e78f784be11bdbfbac4736918c497798d6ed018f529726a6b1894be0658d1b9519538b22bd9afa775903324dbd6028f4e78f784be637002526221bc32e477455b12f864f20b27c44679a2e78e5c56da1ffce8b41bd9afa775903324dbd6028f4e78f784bf4d8ead6c325030538d10ebb39f0efdc2f553794c14a5e45f9555c335925d9d3bd9afa775903324dbd6028f4e78f784bf51bc0b8fce1bae71b76cb3ade28b712669d4e938fd37c9f5872493acc25fae1bd9afa775903324dbd6028f4e78f784bfd4591add2e5b0664363720c71492982d5b223a141a6248246cd2381f67e926cbd9afa775903324dbd6028f4e78f784b1364b7b94ab2a93e79d297ebf6ce0a30f7997e5929e408ef0d3b5d54c64e7b90bd9afa775903324dbd6028f4e78f784b1510988d3dcce120f22696a9e87b02e7fad6367ef4ae8bfd54cdb528a5c48e99bd9afa775903324dbd6028f4e78f784b3860b7c7ff6f4bcd5865843b2e86b2eca5ff4fb071999f2129d4c7753b806f34bd9afa775903324dbd6028f4e78f784b47f7a5f3821286a9c677f66cfe2a84d5ca94cb6fc1ebe8e1986e91edd58cbe33bd9afa775903324dbd6028f4e78f784b52a3ca4db923c0648ac04be86ce02dbc6a3aaac8312366b106205dec6e2ca2d9bd9afa775903324dbd6028f4e78f784b57692fc2b80d809a3be409b44475dded7225c76fdd5ff09e4ed7d330a58733a5bd9afa775903324dbd6028f4e78f784b7836465bdffae768efaedcbaa8b5787baf51b2792a020e80e341a3f824ff82cabd9afa775903324dbd6028f4e78f784b7a0294ba07a2aee3648afc0daf2efd526a5b76349ec906f819c03bc217257638bd9afa775903324dbd6028f4e78f784b85255700890931c5b71a73dff09ea5125cd702ea65f45b4054c1463e00173fdcbd9afa775903324dbd6028f4e78f784b8d5332b350577ab7b1987f93fda104b2090f6a62e262214264f554b6163e8050bd9afa775903324dbd6028f4e78f784b8ed8aa03199de7d541ccbb3009a2b1ff575219662d8b23fba7fdff02d80abd29bd9afa775903324dbd6028f4e78f784b9335c9dd7001a2ec4e322ab6a2d11e6c4cd4ef1644c00d6314b7ba5a26f9eb7dbd9afa775903324dbd6028f4e78f784b9af92541e63eacbc5784bb44db66f9b60726174f4ec178c6ce32eaf647eebca2bd9afa775903324dbd6028f4e78f784ba4b3fee324d25c53fb5cb48630dc80dd7ee78c1aac8c8deea927396997e33bcebd9afa775903324dbd6028f4e78f784ba983e73e57bdf014c9a29331290ee87df37f97c81dbcc43c6c933fe2209c0bd5bd9afa775903324dbd6028f4e78f784bb420509d0d69b294633fd7ae2c36b2b549d45a6a863ef16843a1116a11127f56bd9afa775903324dbd6028f4e78f784bce8c44e185faaa03959cf23229607854ef7e316ed0773d66d7be5e0a48061de5bd9afa775903324dbd6028f4e78f784be808a337ed6911ef561c27cabacabf4ea6d6e20fb70f5413b121ac251abcc10cbd9afa775903324dbd6028f4e78f784be9c71b7cd5a4df0ba48d2ca48e6c468e657257f73f66017de45e18ee746ed7d5bd9afa775903324dbd6028f4e78f784bfd3062358e0e1dc4c3a60380ef1bdfd4c51f4473b8600937d921df472fbf9b65bd9afa775903324dbd6028f4e78f784b65625a143d220ea184dbd5cdfb1b9e9c3bd9654294eaa2b98628bc273ebc18b5bd9afa775903324dbd6028f4e78f784b800423ceb7e4759621a62c729babc81f53259d95f76457224ad601542b7b26d4bd9afa775903324dbd6028f4e78f784b0328f7dd12b552efa7a9e083730333b85f3f4e83d39387fc531863b422f75cc8bd9afa775903324dbd6028f4e78f784b03df4500273c43189296f09d734977c882a008fc056f43c309b9d2351f31792ebd9afa775903324dbd6028f4e78f784b065d94b9ea00397a2addb747e1e0978e4de6bf175339778fb9b0760fec3d3b61bd9afa775903324dbd6028f4e78f784b09f7699631c18db0c33491eb4b3c65b8f279238c5fc5e3ab0ba52737dbbd26f3bd9afa775903324dbd6028f4e78f784b0a3c2072ef4fbdbf045e1876e855bb8ad5dd0809f66ad1442239a7d856ad908ebd9afa775903324dbd6028f4e78f784b0a620707acf23a4e6cdc357a1499e14852b605d9eb6186422f57d458e627d6c0bd9afa775903324dbd6028f4e78f784b16598ee39b716ed9e4765a44abf86906c9b25c25abf631cc78ece6f7211b0365bd9afa775903324dbd6028f4e78f784b17c2b5b96693cdc2951c89dde641d14716063f5fc8795cebc635378b73044e8bbd9afa775903324dbd6028f4e78f784b19f4c7030ad74035f5bc07ace285bd7538f231d25787755d72071ede879c6978bd9afa775903324dbd6028f4e78f784b245e9b81342e45e1baf4f8d830d18ea7fae9fdff05497290ea6442c4ef0ffa57bd9afa775903324dbd6028f4e78f784b3153b3e305575439914605d976cf6ead5a500e54d0b6abcdaafcced1bc47e04fbd9afa775903324dbd6028f4e78f784b36b7cdb6564c58cb54895b6d2c73f88d2908bcbd693bfd253945bd31e3ee81bcbd9afa775903324dbd6028f4e78f784b39abed2935891eef96e2b733bbc6951dafad1a4c6b500d2d9b28c358355a6ab8bd9afa775903324dbd6028f4e78f784b4a4873a319a3a3de35ea325771dffcbb31ec14550a4e029cf0feb9cd686b8c92bd9afa775903324dbd6028f4e78f784b50871141459a21faba3dbbf63da5aac8863fa3d8a9891f182ed72e3a74b64fdcbd9afa775903324dbd6028f4e78f784b54c7d9c28672a1306e43ed7feed38b295f8eec279251f996fa293f68fc6cfb12bd9afa775903324dbd6028f4e78f784b5eb2c76843b253acbcecbb84767697128f000c18358c78c5baf135a5996c037fbd9afa775903324dbd6028f4e78f784b6582dccb8b305efe0bbbafdcc7d295a6a8bf1df0397e1a8ac736e9098a2a64c0bd9afa775903324dbd6028f4e78f784b6730c911e6d91009420d202fb6f394568a06aa97e9f33f30c7e92aaa71332d68bd9afa775903324dbd6028f4e78f784b6f53cd5bf434b19b4e14ca127c596752079d989fcc98bb7d7cf3155619ec347dbd9afa775903324dbd6028f4e78f784b71b601ee3746da7177726db84f5b417c9721583d2d88ad857bf368a54ff76bfabd9afa775903324dbd6028f4e78f784b77cdcfc9644f8f80ff407cde316ac235ddd1ada9c3b6a5aa9544db2d64b79fedbd9afa775903324dbd6028f4e78f784b7c09d8b90b72b7c2ccf1a413e335c2d1a25d75bb8541f9bc16b4c4e26bda6855bd9afa775903324dbd6028f4e78f784b7f964730cfb7b8cea284e2e810212ff9b0ee18227f64427a095d6886493db0c4bd9afa775903324dbd6028f4e78f784b84d75f7a8913d66db946eaf1480eaddec3063d27a6f625f040b406718abcac44bd9afa775903324dbd6028f4e78f784b87176a15e766bd06528ed91a61481c3b3cde65ee95115403f9ffc6d3a26d43d0bd9afa775903324dbd6028f4e78f784b8cb4fdae88f4f492ac6c87716602366df1ac84224b85ab2d3949f5aee79cefebbd9afa775903324dbd6028f4e78f784b90a483526b4238c55bc5ded289d7c1d376109b9d5f3e93529eda75c4d451523abd9afa775903324dbd6028f4e78f784b915009d1cf9d68b9e53064de82d4b70b58d2f014a03805cc406427d323d9fc35bd9afa775903324dbd6028f4e78f784ba0107a564e93989c57044fd18aa85beb1258101ac3d9f6e10bf12c1c6573bc2bbd9afa775903324dbd6028f4e78f784ba330fde65c067a5f0b75c80d0a300767c301eb75e0cf9b4ee240f0d60b3dc503bd9afa775903324dbd6028f4e78f784bb149b29e8211e24827fbe0168d30cb2619cd3365bd6f8173e7a731c5f702dcd9bd9afa775903324dbd6028f4e78f784bb97915da9f05277fa5687f8c41132df69152517f2ba252d466395b40d4f2d155bd9afa775903324dbd6028f4e78f784bbb44fd8cd04abc3b54e5ccea97ef81e70fd3933c34288d8b86f6ecb4f3ed1fdebd9afa775903324dbd6028f4e78f784bc1547cf902570207a9694b6b8e353fe41419db6a3802221ddf10fb8f86947804bd9afa775903324dbd6028f4e78f784bcef75d1da8e991ac96d36f8a14562849207f9dd50fc63028ba83277d5c27d00bbd9afa775903324dbd6028f4e78f784bd5bc11fb619bfced64249b930c785ead5fca3927f0ce3c5efd3f1d9af04b37bfbd9afa775903324dbd6028f4e78f784bda9943277174960b0d7d3f0d656176f3723ed2f03a90518beb3c6c202b88cc14bd9afa775903324dbd6028f4e78f784bea9c72c1ce865e6044abff576fd712d4df3f5114318753efcfefed70ee586884bd9afa775903324dbd6028f4e78f784bf1cad3ac005b57d6e22ea57b9ebe1ee9e5052bdda499f5f2c1364317de87a794bd9afa775903324dbd6028f4e78f784bf74947590a87a005023e9ef89cdf0c38d8d582ca4173f8201cebc443ef796790bd9afa775903324dbd6028f4e78f784bfb0bbc256aea5cf93da99cf26481cc42f4e7ba6b32db63b827620807e79e805cbd9afa775903324dbd6028f4e78f784b0c0c78837fa767eb045b8199e1e20ad666f90928daeeb8f5e5253d8e7877fcb4bd9afa775903324dbd6028f4e78f784b0e44212badf40d6b8de3311e632045370588e0b23b7a480eb5dc10db65d1b4b3bd9afa775903324dbd6028f4e78f784b13dba28447fdbe3c8a24fee3eb88638ce1d8f97cd4925056c0ad0e91ca51237dbd9afa775903324dbd6028f4e78f784b1da53f3a2c7c41c93099737266b5619ff616a433fb3b870234622d7aafab9a7abd9afa775903324dbd6028f4e78f784b23fcd6bf3084cee6a9f9885e5239230b0adde0c870589ee461551d1ca8f4e85bbd9afa775903324dbd6028f4e78f784b264cbc5765718a0bccb0f79c0fdd133a898203fb6f4f2052cb0647fbf6000ed0bd9afa775903324dbd6028f4e78f784b266c1429c8dc389481b3814bc3af8723db28eeceb0bb026bbbeda0cc41d36bc3bd9afa775903324dbd6028f4e78f784b2b1b9eccf585b11c5122651d7b94534bb131aa7c874e2262038b85db3ee83e4dbd9afa775903324dbd6028f4e78f784b326967c7ffc1b86db8b32b0570e88a89cc1534cfcf300b98c077e473f9b18fa1bd9afa775903324dbd6028f4e78f784b332450890f9c8fff7ec15c53921bf27227ab9ea06b0e1c816d819f8e21cfb55fbd9afa775903324dbd6028f4e78f784b3b7696df627ade30bb15bdc5ce3f3c27240c973353e8551e7b036c90d01280c9bd9afa775903324dbd6028f4e78f784b54061ff50d91296f2f44d8b338aeedfbbe86df49db5de8a45191aaa931f5bcf6bd9afa775903324dbd6028f4e78f784b586898c60cff539b76d23dbf2c92e4105f6a7549e13f53d293708b793ca90d2dbd9afa775903324dbd6028f4e78f784b5a47b0b11d2fd9cd39c627d1e6bf4afed9601aa15d6a5d84fb10f39755d2d323bd9afa775903324dbd6028f4e78f784b5e67bf240b1d05f6f618908868a494c50a30ab255b06619fa28411eb260f674abd9afa775903324dbd6028f4e78f784b61535caa144761fc48cc9d7a835dfaf020b569edfc7fa628f983d58a3ac25f2abd9afa775903324dbd6028f4e78f784b691ba3414e78622581bc519baf0bcb16fb262d3abbd8639f3e0eca2a29f99406bd9afa775903324dbd6028f4e78f784b6ce1f2986f0c46683ba07d296d0a84448ecf76c69db183fe29c36eed8f8e8f2fbd9afa775903324dbd6028f4e78f784b6cfddb6203f254d38a5bcdd4173d51647a487ca70ab21326aca0a03bb3d2bac0bd9afa775903324dbd6028f4e78f784b736afb5df29ec9c88532be9c620ef80901bf23e72f2d3488b757aff17e734acebd9afa775903324dbd6028f4e78f784b74b39c206dc8a11cd196d5998d2996b6ad477d72eaf86e19a3dc14ec0eab0f1ebd9afa775903324dbd6028f4e78f784b7c7372a60d71e04879b8930c164944d96d3753e0a2924a31231d1d5fb97882f2bd9afa775903324dbd6028f4e78f784b7f292bce8dc97b601ef1ea72bdf7d96a12a87782bb1b1c547f85c55c7b3ff035bd9afa775903324dbd6028f4e78f784b812eb0fa2df13a889549729cadbf1720b68f6c9e21955741b72802590af1b5cabd9afa775903324dbd6028f4e78f784b815d98aee498cf27fd6648c7e02cfc0a4a88aa73237cbb2352fe38384a72683dbd9afa775903324dbd6028f4e78f784b8a305c5fbe7c56f9e3214d7adb8f176341f4020f234f3c14e52335967a2d365fbd9afa775903324dbd6028f4e78f784b92185c264285741fa7f198cad8f307c60891ad932d9e3c2a08d92546ff7099edbd9afa775903324dbd6028f4e78f784b92f858f6a02bd2014618b05d7759e34e7781b15c34c8814ba4c930b320f8db09bd9afa775903324dbd6028f4e78f784b9414f5fa5853978c07fc6bb17a1ca9460fe443ffca021fa52c8672a94460f44fbd9afa775903324dbd6028f4e78f784b9ebda9554ad5bb9e3d5ce700f7c86d4f5b0d782bf1dbf30a6a7234749a5dd517bd9afa775903324dbd6028f4e78f784bad16de1e2ba27196395124683b80efc186ee7e51d434f8ff67d973f46e8e602fbd9afa775903324dbd6028f4e78f784bb4938ed2ff001b73ef31e5bbbebe1d6dbb7d9888a9fbe5251a52a5ed016652cfbd9afa775903324dbd6028f4e78f784bb67db8d53c925febadafce4356206c85f73e22456eae4ed6ee77f6a9e11a078cbd9afa775903324dbd6028f4e78f784bc470161a06e6b452253a623536924979cdd11838e08d8e4dc86f763732e64b0bbd9afa775903324dbd6028f4e78f784bcc7396d1c306adfce49e70d7daf32d093a8f2febe2ac0576ba853770e11b3ef2bd9afa775903324dbd6028f4e78f784bce1af9fcce6ad19c00d8236b23b03cf83c593c6184a08266e58fe95c6caa4d13bd9afa775903324dbd6028f4e78f784bd417c004525c7bb57523836278cee120fd66147983ba738aac011e24be75e6e2bd9afa775903324dbd6028f4e78f784be2cf881cf07195454505047d74810ed79ae20dfd0f1593afbbf08270a486c038bd9afa775903324dbd6028f4e78f784be7d9bdbcc68b5bed590c29b72dca2b96779b8b68b12a47ded074b8f1b32f8fbebd9afa775903324dbd6028f4e78f784bf197a171a09ab640aa8ac4ff7ddfc88377a89fdbb3fee014abb9097d92575b67bd9afa775903324dbd6028f4e78f784bffd7688e7d2b8c3c3140b415e728bbe7663c54e23bd288ff2cf4617835088f39bd9afa775903324dbd6028f4e78f784b450effc827ca535a79d5c4ff3e1a3f614ca9126b3792f997d38791ca7399320cbd9afa775903324dbd6028f4e78f784babee522892fa10b22208b4d1540184617bc9875c9e03e5353b4ff476577d918bbd9afa775903324dbd6028f4e78f784bf254087746fdb5d9d9eae6df458485752beb0fcf295c36d273511b45f7480287bd9afa775903324dbd6028f4e78f784b996c1d55955dfb3698869bdc2a700e6bcc762468716b5cbda7295cf98841220abd9afa775903324dbd6028f4e78f784b6b54497ff9915a6977428bdf8f45b116d874c4f8a836b5bdfc373d05f4c0ef87bd9afa775903324dbd6028f4e78f784b6d174dc1673f7cfb6f1ea75d71739afde2b784e214e41ae6f5aa30f622a400c4bd9afa775903324dbd6028f4e78f784bcb95a4d2e0e02a5b56d059c9f223c2326753ea8c44d2e3fa6c4486629be387a9bd9afa775903324dbd6028f4e78f784bdc7cc8d1dc11e304abdf6e6227838f35b223b780f030de7b341e88a3f6a361b4bd9afa775903324dbd6028f4e78f784b8806cf0c7bd5df7e01d120f56734113be916e183755577bd48026c25db268680bd9afa775903324dbd6028f4e78f784bce65c29521cd8498fad962e5f70d55c5044366ec09c761a60cc7c4a2001776a4bd9afa775903324dbd6028f4e78f784b2992068e4f616f2d7253e9d58116a97f22923f4dc1b78a58be4499b982ecf270bd9afa775903324dbd6028f4e78f784bd87817f76309b1e420547808cb573aea0c8e7de14123793a42388582184286b7bd9afa775903324dbd6028f4e78f784bcc202e8f2753ec75c9eeaac65c9d39eea6faed570664e930e3815976cd332d91bd9afa775903324dbd6028f4e78f784b7b94f0505f37b19b432aba08be2e3e003038c02ceb531e169d460db60c351649bd9afa775903324dbd6028f4e78f784bcfd2a8f23bbce7424f4a6e27def368f17b086ffa226528900fa092736e705ef9bd9afa775903324dbd6028f4e78f784bf0b3d0d4c5457880e2d9b7728eb64bd288b5d4a26ec883f3c0941d8af29d9466bd9afa775903324dbd6028f4e78f784be8818666b7e014b6e4820afaa84d5a84fa42cb5d2663c848d358b2913274ba21bd9afa775903324dbd6028f4e78f784b21554d1f3bf9f52d3cd297d27df56215c0fd08a0bf673868f3d8c6c064dc5609bd9afa775903324dbd6028f4e78f784bf8f38c4febe9d8e45e71a459c5bff171755c348d5f619f3c6ef30a3f8fd02bd1bd9afa775903324dbd6028f4e78f784b8ede7732284dab4aa384606ca07be29e72fded094597261a2f6473494a8aca0abd9afa775903324dbd6028f4e78f784bcf7f9e7d091023a1a1c3f5cbf7ddacf7b18f03a4d07961f71506fe9df4388eeebd9afa775903324dbd6028f4e78f784b2b21029fa033526d1dcd9e87ad8893f9b5a08987c3271b8a86716865de53d958bd9afa775903324dbd6028f4e78f784b13a1f37bedfb5417b6b737e2a3816c8fd587d74d836914b2b2edc9fd6ca30e58", + "time": "da070306131115000000000000000000" + }, + { + "name": "certdb", + "guid": "d9bee56e-75dc-49d9-b4d7-b534210f637a", + "attr": 39, + "data": "04000000" + }, + { + "name": "VendorKeysNv", + "guid": "9073e4e0-60ec-4b6e-9903-4c223c260f3c", + "attr": 35, + "data": "01" + }, + { + "name": "Boot0000", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "090100002c0055006900410070007000000004071400c9bdb87cebf8344faaea3ee4af6516a10406140021aa2c4614760345836e8ab6f46623317fff0400" + }, + { + "name": "Timeout", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "0000" + }, + { + "name": "PlatformLang", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "656e00" + }, + { + "name": "Lang", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "656e6700" + }, + { + "name": "VarErrorFlag", + "guid": "04b37fe8-f6ae-480b-bdd5-37d98c5e89aa", + "attr": 7, + "data": "ff" + }, + { + "name": "Key0000", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "0000004051d7979f00000c000000" + }, + { + "name": "Key0001", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "0000004051d7979f000017000000" + }, + { + "name": "525400123456", + "guid": "937fe521-95ae-4d1a-8929-48bcd90ad31a", + "attr": 3, + "data": "fed73a9a88c103003400afaf08000000010000003000afaf04000000020000002c00afaf04000000030000000100000001000000505400fffe123456" + }, + { + "name": "ClientId", + "guid": "9fb9a8a1-2f4a-43a6-889c-d0f7b6c47ad5", + "attr": 3, + "data": "0e00000100012c0a06ed525400123456" + }, + { + "name": "Boot0002", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "010000001600550045004600490020004d006900730063002000440065007600690063006500000002010c00d041030a000000000101060000047fff04004eac0881119f594d850ee21a522c59b2" + }, + { + "name": "Boot0003", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "0100000056005500450046004900200050005800450076003400200028004d00410043003a003500320035003400300030003100320033003400350036002900000002010c00d041030a00000000010106000002030b2500525400123456000000000000000000000000000000000000000000000000000001030c1b0000000000000000000000000000000000000000000000007fff04004eac0881119f594d850ee21a522c59b2" + }, + { + "name": "Boot0004", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "0100000077005500450046004900200050005800450076003600200028004d00410043003a003500320035003400300030003100320033003400350036002900000002010c00d041030a00000000010106000002030b2500525400123456000000000000000000000000000000000000000000000000000001030d3c0000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000007fff04004eac0881119f594d850ee21a522c59b2" + }, + { + "name": "Boot0005", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "010000005a0055004500460049002000480054005400500076003400200028004d00410043003a003500320035003400300030003100320033003400350036002900000002010c00d041030a00000000010106000002030b2500525400123456000000000000000000000000000000000000000000000000000001030c1b000000000000000000000000000000000000000000000000031804007fff04004eac0881119f594d850ee21a522c59b2" + }, + { + "name": "Boot0006", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "010000007b0055004500460049002000480054005400500076003600200028004d00410043003a003500320035003400300030003100320033003400350036002900000002010c00d041030a00000000010106000002030b2500525400123456000000000000000000000000000000000000000000000000000001030d3c000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000031804007fff04004eac0881119f594d850ee21a522c59b2" + }, + { + "name": "MemoryTypeInformation", + "guid": "4c19049f-4137-4dd3-9c10-8b97a83ffdfa", + "attr": 3, + "data": "0a0000008000000009000000120000000000000080000000050000000001000006000000000100001000000000000000" + }, + { + "name": "MTC", + "guid": "eb704011-1402-11d3-8e77-00a0c969723b", + "attr": 7, + "data": "0a000000" + }, + { + "name": "Boot0001", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "01000000200055004500460049002000510045004d00550020004400560044002d0052004f004d00200051004d00300030003000300031002000000002010c00d041030a0000000001010600021f03120a000000ffff00007fff04004eac0881119f594d850ee21a522c59b2" + }, + { + "name": "BootOrder", + "guid": "8be4df61-93ca-11d2-aa0d-00e098032b8c", + "attr": 7, + "data": "0200010003000400050006000000" + } + ] +} \ No newline at end of file diff --git a/tests/assets/efivars.md b/tests/assets/efivars.md new file mode 100644 index 00000000..3ddc1e0f --- /dev/null +++ b/tests/assets/efivars.md @@ -0,0 +1,18 @@ +2 Files provided for testing efivars + +efivars.fd is the compiled efivars in a format that qemu can understand +efivars.json is the original json from where the efivars.fd file was created + +efivars.fd can be recreated by using `virt-fw-vars` from the package `python3-virt-firmware` and is used to manipulate +efivars files and generate new ones from templates. + +Assuming the OVMF package is installed and the default firmware and efivars files are at /usr/share/OVMF you can run the following to regenerate the efivars file + +```bash +virt-fw-vars -i /usr/share/OVMF/OVMF_VARS.fd --set-json efivars.json -o efivars.fd +``` + +This uses `/usr/share/OVMF/OVMF_VARS.fd` as the base template (is empty), loads the vars from `efivars.json` and outputs the efivars.fd file + + +The current efivars enables SecureBoot with the default keys and also bundles the certs for our testing, available at $ROOT/tess/keys/ and what our test UKI EFI files are signed for. \ No newline at end of file diff --git a/tests/go.mod b/tests/go.mod index a12787cf..49e26447 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -12,7 +12,7 @@ require ( github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.7 - github.com/spectrocloud/peg v0.0.0-20230825092931-25d89833e022 + github.com/spectrocloud/peg v0.0.0-20231002135825-d1dc260381ac golang.org/x/mod v0.10.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -29,6 +29,7 @@ require ( github.com/codingsince1985/checksum v1.2.6 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/creachadair/otp v0.4.0 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -124,9 +125,11 @@ require ( github.com/quic-go/quic-go v0.34.0 // indirect github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/urfave/cli v1.22.10 // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect diff --git a/tests/go.sum b/tests/go.sum index 3e863b77..13a59912 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -45,6 +45,8 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/otp v0.4.0 h1:3PBnESxegU3hQ0D447D75lSnTtTVfw6Eny8GviOXcqM= github.com/creachadair/otp v0.4.0/go.mod h1:mDkCUSoWN8zqxFoDMw20Boe6xeDd1jJuy6pNQQ4lCy4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -430,8 +432,11 @@ github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtB github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -471,6 +476,8 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spectrocloud/peg v0.0.0-20230825092931-25d89833e022 h1:/dw2RhgT412X7iXzGBrUNdwfV914VjGsakISm2Ual5Q= github.com/spectrocloud/peg v0.0.0-20230825092931-25d89833e022/go.mod h1:L2fIdtZqbQEagjOOXwkwH3t7MjJUd7fbt52cLSQGDBg= +github.com/spectrocloud/peg v0.0.0-20231002135825-d1dc260381ac h1:2AQBW7nOjdTy11UvomVwltuYPQyviEw+zOQ3IOO8P1g= +github.com/spectrocloud/peg v0.0.0-20231002135825-d1dc260381ac/go.mod h1:L2fIdtZqbQEagjOOXwkwH3t7MjJUd7fbt52cLSQGDBg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -490,6 +497,7 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= diff --git a/tests/keys/DB.crt b/tests/keys/DB.crt new file mode 100644 index 00000000..213756bb --- /dev/null +++ b/tests/keys/DB.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUQ8Ef+QHp6mLYXXvX8/9YsKJDINYwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJS2Fpcm9zIERCMB4XDTIzMDkyNTE5NDg1NFoXDTMzMDky +MjE5NDg1NFowFDESMBAGA1UEAwwJS2Fpcm9zIERCMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA7yiYejq/rA33hFx4D2pg8pbCfZFpA2r1CGgJpaOw0emY +m9pe6PmHhfT+mifXUao3mC9hjtB+cD/LQNlu6gR4x6UMs3c6+i+y1PMldsO/F2vS +0mNz759BEawiO4x0bopr+oPJSvpkP5UUjYvJ8Cd5q5ON4rBEeCT9d8E9nG9uH3XQ +oQPAvzo9ehhnzAAmHS35i2hSl6rUMgwp6S24CKcGbwl1pNvoU528W0xr1hYOazba +/+rZQtuGqscUYUAbOLE1hOp/UWGms/m0ezTBsVkQ1RyQn6cWGrKVpTzaaN+1e5ai +xYyXc9/QzY5Rqd4qisTmwYBsHdeVhXp3ihJkWnTzrwIDAQABo1MwUTAdBgNVHQ4E +FgQU1McSdX5TgJ/FcIjI+SNwm6ss4MwwHwYDVR0jBBgwFoAU1McSdX5TgJ/FcIjI ++SNwm6ss4MwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAzO5C +E5BjEhwq050bxqqVDYGYXXaLHQsTBDeJGSnJnggODz4o5aKCiBjOAvNeT46maHAe +g7jJ4eNw5Beiqu2LQoTFQC/eCFs6frYRBNCewPMezmT+i+YqZvc/RZfgTY+64SRx +AHvfJuelU3pAS2gWAeg7gQZa0KTJG0ZWnULwy+pAcN2yckz5NOZ7Hl2PPTCUGyhz +uIgoZp1ds4xd6LmGssuMZB6phyhAdvhokrYesJT9BT8tCGgiqjUZWSpG8gJBoJXC +2KHn5iE70B4V/LICBa20PucH7rDgaJTJaKOJ5hp51S6dCUAt3prgPsD0sx+42LvN +OLolFoaI8pH5yJOehQ== +-----END CERTIFICATE----- diff --git a/tests/keys/DB.der b/tests/keys/DB.der new file mode 100644 index 00000000..14468da2 Binary files /dev/null and b/tests/keys/DB.der differ diff --git a/tests/keys/DB.key b/tests/keys/DB.key new file mode 100644 index 00000000..71e79602 --- /dev/null +++ b/tests/keys/DB.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDvKJh6Or+sDfeE +XHgPamDylsJ9kWkDavUIaAmlo7DR6Zib2l7o+YeF9P6aJ9dRqjeYL2GO0H5wP8tA +2W7qBHjHpQyzdzr6L7LU8yV2w78Xa9LSY3Pvn0ERrCI7jHRuimv6g8lK+mQ/lRSN +i8nwJ3mrk43isER4JP13wT2cb24fddChA8C/Oj16GGfMACYdLfmLaFKXqtQyDCnp +LbgIpwZvCXWk2+hTnbxbTGvWFg5rNtr/6tlC24aqxxRhQBs4sTWE6n9RYaaz+bR7 +NMGxWRDVHJCfpxYaspWlPNpo37V7lqLFjJdz39DNjlGp3iqKxObBgGwd15WFeneK +EmRadPOvAgMBAAECggEAAcwXzT9YxmW6ePOq8U622MvaPVBU7jIlEkGZ5PVEdGdh +frZW5UBOzOpo6WaoPxRc45djj8uwT46jK+MWasrKz5FFdanNNykZmnETVH+nFXl5 +dZxKuD/FoOjevvzQuS3wHstTvW0BSNsJcwDcbSIWz3vF4rC5av+4Kei5Wk4aEUFx +Ll/mwtDNbkXPRK1xXWg8Z69BwPIxIo9CESNkwRAQZr/1btBUXaMpHjmF8c76vj8z +ayD9gsDLGNYnU11cVbdlREi0J5CIVyPbBFuOoU27U9scTBJfrRBCCRLe19N6B0cQ +LEoLCdaG4CJz3kGX2ErBRWBu2w7qHZd3rD0JdE9KfQKBgQD3vHlT34+MFVG/4+z2 +8kfThHA/EfseK7KDy5FUGMomFXVlR5+6UbWmWcbjN9wl/iB+FfkYYSbX+gS0gYuq +hwlecIIM+sbPly0xjVvTXf8iihzaZsRx+fCfctHi087ZvbhCHXgYHRSBZ1u0dKoA +y4rnpeWP0I9ZGBvNznah2baCrQKBgQD3It+Z+7Pr1O1cBdqBHRJtzO1z1s2Opj5L +NICjHXCEcU1GzR1rGc20FXXaDcMbgisRob1w92ESrxHRsypUlboKtMfcf0/HbckN +FZLDxkxZENBUql9DenT69m4hEFn3KKOqi2D/RVjYBZrU+joWkv3tXcXiBjB+srgw +xeU1+j+3SwKBgQDoWPKKAZFGVvB3QrQK4C0RapND8/9LyrwA9Dn3X9Coa1PRi515 +SA1QWb85eDiXwYKD/uPDQ8sEoU8sZJuzcjcNRgQTXFh+dlFCuku3L9+Ma3CoPd5c +74gIY84KKZFFkrRv/eeW5h9HRsMxuoF/gWdj36owefEYJI5fNhb5sZGFeQKBgHxr +ICtDnuchwYXMpJ7P5hFFVF43TDF+3Gm8Ou7jyVvENuVoKmFbEkaRb02iFBHrTIeJ +5/fRcxuW69+o1azT3F+7d8s4hQ+f49IkhEjvskw8vMWDKIauRep62iLnOoPF/+/C +T8j0PrAy0ipa95eZ1SEFTrRl7VA75aMYXjb4j89VAoGAK+7UBmtTOLTVNUxNFXIP +66Ue0ZX+FOLollJYx42QvXmoqXayOb2H5EjZIIW3narom5Ox454zlWbty4Luncqr +bhfKBLhPqeoOw05h6Z+s9lfr++7rR6ZC8Q+r3m8W2MiEAVDxPIucwB1FPoy2zFG2 +jOLVMOsPlJ9FcRQKWupurdo= +-----END PRIVATE KEY----- diff --git a/tests/keys/KEK.crt b/tests/keys/KEK.crt new file mode 100644 index 00000000..6cad9ab9 --- /dev/null +++ b/tests/keys/KEK.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCzCCAfOgAwIBAgIUFElXQYJNL9OmNok3nLKNWzDExuUwDQYJKoZIhvcNAQEL +BQAwFTETMBEGA1UEAwwKS2Fpcm9zIEtFSzAeFw0yMzA5MjUxOTQ4NDVaFw0zMzA5 +MjIxOTQ4NDVaMBUxEzARBgNVBAMMCkthaXJvcyBLRUswggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCapyZdRd6TFgnrJJtYYUAgfCfFSzpRQLorYgqUfaY1 +UnNxlE1ngcBs1GHRQAO7jdYPvL3QiIY+qKoDGJ12/UKs6SpfNHLQtHQ2NrQrVDXF +gt+ttauhsa+T0ll46qDc3H6x9s1jUhGIFZgkmQ+aXj5YFHwjDtoxw5vtJw/p77rj +e4bEs58Fr0ovrlDm2en2kpiVvXSQdWxy1pLBt1QahfZf4jqgQJ13A+oURx7pgyoM +ayvtVjG4lLtkkPm5L5JXImGG03XkjOehckKoQR88oAmhzzDat96i+18dMd3HR2gk +V4/hXQnPPtCffHBV5r26kqe4KojCx9riz3yEylvMMtE5AgMBAAGjUzBRMB0GA1Ud +DgQWBBQ8+vEr6ovmH40ZA5FJiT+zYLBitDAfBgNVHSMEGDAWgBQ8+vEr6ovmH40Z +A5FJiT+zYLBitDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAw +sjmqYzHnQF06SlICMh06obnXSkzf06whvkhl+mWUMBKVtMFR6D3sHs7pznNhMkpY +Fa9j6hY44fjU+6tkQaMccz/KOMDKpJlPmILKuixraYgCV7HcoBmpKE32xwCzEId3 +NZ38JDxRFmijIDtdCUspHxeMn+PpHDhkvBdEK60+bA7BZis9b2qDoiAo6NpxjdVL +kMBVzdGgqGcN6SPNujgy78/N/vndxGRxyN2fscmnvf0qzs1OP696AyTDQ9VZ/4fP +Q/kmLfL9JNu8d4cx1wdgV/20FtMnHhr1Q7f1/Gqr5S2zt3L9WLwnTDOrLd3UZ9wl +wtpRye1107RaagwlTnvh +-----END CERTIFICATE----- diff --git a/tests/keys/KEK.der b/tests/keys/KEK.der new file mode 100644 index 00000000..1a01f4e3 Binary files /dev/null and b/tests/keys/KEK.der differ diff --git a/tests/keys/KEK.key b/tests/keys/KEK.key new file mode 100644 index 00000000..7cc3981c --- /dev/null +++ b/tests/keys/KEK.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCapyZdRd6TFgnr +JJtYYUAgfCfFSzpRQLorYgqUfaY1UnNxlE1ngcBs1GHRQAO7jdYPvL3QiIY+qKoD +GJ12/UKs6SpfNHLQtHQ2NrQrVDXFgt+ttauhsa+T0ll46qDc3H6x9s1jUhGIFZgk +mQ+aXj5YFHwjDtoxw5vtJw/p77rje4bEs58Fr0ovrlDm2en2kpiVvXSQdWxy1pLB +t1QahfZf4jqgQJ13A+oURx7pgyoMayvtVjG4lLtkkPm5L5JXImGG03XkjOehckKo +QR88oAmhzzDat96i+18dMd3HR2gkV4/hXQnPPtCffHBV5r26kqe4KojCx9riz3yE +ylvMMtE5AgMBAAECggEAJCuz7VzKEdy1tSl6q9ETDoX7R0mw+hAJetwTXWeF2DLQ +jWACOpM+TjXeKvKt7M/foQ6j1oIX48/O86puKcZSMd7W6i16LRYHmCZzPS8U5H0X +k6lJ2yeTyR8Jjh5SQVXQzA7NOs2XDB0A2I5z98bTDga8gfaXUcxOS8k3D5/iNhHw +oBWjk9MSkxXPDS67mFOZGeia+CcG/k3r/GXrakBj8Iq183X0GH53VJr+y6DLXJax +tHdg0mio57HFvG7LvzODy25Ymr/r8RFIuSqrCEjgeQQt/oERqVToZDFB0pELgSK/ +A1JuPvPWT2CXPymXHl9uBJvNQS1eaoI+wKZ0ui7BgQKBgQDZpo6fdMR88Z9RDLgk +E6PfVNxq4KHIVtSErpGYKVx56CIVrhOu9Jk66kJq7eQma6UCUZd6qHMx9CG/ligZ +yk4u51kDM2btqRdtsnXbKiqONcoorn6E8UZHSJxDBrRSAUIruaJC+zxwACVtwasz +4Pc5HNvqFGqpMi7ujs8rP1/hZwKBgQC15v3sKv54KZwOxEGxdabRE/T/hQmiasG/ +34qdNV/DRDLxIpyBPbKR/EjJyNsFzzySLG2oeDCUY7JX1B9iZ24RgT8OmTka0nSW +yi4RhH99hzLglDCHe55Zrr6oDK9xwhxWKIHU98hNVCKGDptd5HQ140sdZTwQsJ26 +RYbbj/j0XwKBgQCQjEpqYj1gkYPyaxUceKK73vsoTBmGGQy5NcriGI4fNGj2pw7R +ggcGFrCXnXiJf7IuEQweXSNsSKvlNo9ZWX+FLQZz1r6EFmnF4+Db9mwe2GBzljfW +iPrYusN0zE4TrFxK99Vo0Lw50g8JjrbqFH18Q8tV8ctIpVh//P5fxY4i/wKBgDhk +2shDNA1Q6R7y3WMFFKixRT2Ko0gFTPgNd83xZDUHibuUfWzcEeaMjoxwhuawLxkq +SPz39ierGPl9vBUn98nZhhEik7+rC5ZMLCgmKdhi9/UEPF9khd1L/bPf6uybv2k+ +ubGq+CBxOxrQoH5le1nRk9ITNqH9/4hmUb70TbyFAoGAC0w4pJM8R3kaFqKdDVo8 +bD3buojiE0ORPeLdnhe5yc9XaLsM6Ti3MPCeiQ3gZRCuvOlsy4noDnATUXYusNfa +u7WLPO56ne5ewAWWmtywQ/D8IZHWHkNM1n8yHWCZXyZgF7sh1CXsIXOam7F9Syzm +8uZGoFciL4vV9F5x3CBk70M= +-----END PRIVATE KEY----- diff --git a/tests/keys/PK.crt b/tests/keys/PK.crt new file mode 100644 index 00000000..a37ee522 --- /dev/null +++ b/tests/keys/PK.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUeKRpRkHvYxAffzrfw90J8MAlTDIwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJS2Fpcm9zIFBLMB4XDTIzMDkyNTE5NDgyOFoXDTMzMDky +MjE5NDgyOFowFDESMBAGA1UEAwwJS2Fpcm9zIFBLMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAqfXx/rkk1TPZTWisQFnhRr5T8t6I7i9zK3DO+URrsg6V +7+5ztM8udc1RUg1VndkZRNMKazgVqH7ZfKHkxUdQc4Xq+EKscywJirtcjsMKVAUt +IEt9M/NeQN+CIEsSgOyEqJZGazcVPpL8Q7x4xcZ4SewJyobS5u+txY9Ei/EA40ih +AxycYmhoUHLLwjtO9O1UKf/6HW3KgkMYpAualrJjd70g0WsV0lFGUCG4rpSEN6Dn +p17zF1y5USCCstgxp3KSMuBFlBFzFChjy6w8v0LUlFADYj6Z83oPOD/2x+UeJui8 +Hxcrgu3VnXVmLoQaggml1EqbW7cu8S3YxlbAH5pQrwIDAQABo1MwUTAdBgNVHQ4E +FgQUHzloQNy/RNHN71Ihn0YaxwhdcrgwHwYDVR0jBBgwFoAUHzloQNy/RNHN71Ih +n0YaxwhdcrgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAASMw +sw9kOeNNhcA4o5MnIG6uqH/4jIMG8UjcqyuNKtH/2eLs/xNCSDIJG0VVuY2y3kzw +GLZmphdxvtvWW6c9A9+mdM/JBi3AeGyIGk2hfFVoFcV/7VuGgphAJcTKY6KXgj7e +F6hjatCCUUYiRkiPL50X5wJQ/COAOe7/5BzeAZhbxNQ9z6IG4StdS31uSE7Vl2Nn +G+V1Gkqmc/6Z3Nkd2iGPiLIiqkDn8Xcincn/f0ybgnOdVljtXlzJm0pN4FrVkdPa +en/HLiMCjKTSWl1wXF3GUZkmCITryJ4O6SWtsuWTqmvohb2QAMqdnybFW7hjzGoG +A0UKl8yqRzdGBa0mHg== +-----END CERTIFICATE----- diff --git a/tests/keys/PK.der b/tests/keys/PK.der new file mode 100644 index 00000000..97b65b5c Binary files /dev/null and b/tests/keys/PK.der differ diff --git a/tests/keys/PK.key b/tests/keys/PK.key new file mode 100644 index 00000000..6f28f9e9 --- /dev/null +++ b/tests/keys/PK.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCp9fH+uSTVM9lN +aKxAWeFGvlPy3ojuL3MrcM75RGuyDpXv7nO0zy51zVFSDVWd2RlE0wprOBWoftl8 +oeTFR1Bzher4QqxzLAmKu1yOwwpUBS0gS30z815A34IgSxKA7ISolkZrNxU+kvxD +vHjFxnhJ7AnKhtLm763Fj0SL8QDjSKEDHJxiaGhQcsvCO0707VQp//odbcqCQxik +C5qWsmN3vSDRaxXSUUZQIbiulIQ3oOenXvMXXLlRIIKy2DGncpIy4EWUEXMUKGPL +rDy/QtSUUANiPpnzeg84P/bH5R4m6LwfFyuC7dWddWYuhBqCCaXUSptbty7xLdjG +VsAfmlCvAgMBAAECggEABfVOzgC8l1LRf+K3AyyDdsDuXXnKsBruvSufveJVqjDT +tc0UtlZ7CPsxKiC4iyeUuLJzT43wSG9l/XYJeJcG7X3Y3mor9H+rN/dYh9Kzln11 +9wdedMdH2xtayvoGxIlGH0jhYBnWv1JU0KUXUMuj5OeG8lgmpZzqaR4cJ5HD17Ph +3e4kMdtSdNVvV4UxTp7oiX9KYrNueAnqh09O2Hq23+6LV2yB5gs+wBlzpXECLma/ +UmNJOzFpLIi1HHIDgfdwTS0JnP4lGPEV+R/VHdHfy9W9WB8jyyONPewCtaUMqgxY +W7kZCrjRmpMVzQwA/60SIaFZpdSQjEDNIMssl4bozQKBgQDtTQX6LyT/RoOKbv5I +n6Uqi5XFU+k3SnDHN/8sTSwK7r4xC4n+2MjR0YS2tDYgaAvqvnG3dCRP0/NYluSG +0Ih2g2t1ct+feWbvd/a6On8f2UoNGC0X4xoLmNOe/ToqcAFTW7TJ6l6oQ5fGq+QV +UczwkkKToYmjFjgY5GMCUTbGRQKBgQC3Wn7p9V1WadQMPGRu0LegTCV4QZlkiLqw +OE9Ezg8GgnyJ0ny3FmBPIPAMS/h6Rex83fBzds0uDLSkRSpTprqcbLr6lFL3Mf7N +uPXxUHOFvc4P7sHK57jVYlV8bu+OQC3XLaIkjguMIVoZZR57q1rCN3KwZ8FPXyCb +GgVqRTlUYwKBgQDTSAPtaHJpc3AFHqP7J2FYiyWTpw17tCTLy9i/qgpvxXfDlUGN +jZjn78NZJQUYP2t025HGRHtcNBtzog3g1uTZmFNiJCBlDiOPTWF5GEI9qirbk836 +ebKj5rNs2IwkYstbW8iRCsKy0FPfiQYv0UBGZgMvDOHOOidCSn64/nRlfQKBgDYB +EpaIbYhxPUKpWw+ErEErjHHCKJMC7rHOtBJY+vX44wOZGqC2l4FW+z0z9yjUhZY1 +rIfluwNQPLiRoqjm19oQ8HWz0Ef80sb3LoF4J76BrDrnIO9JlxhKkVFIP4jPgHD7 +gOFxcRdCD46hSPw1+VJxEHfC554gL7NfU678WqlvAoGAMeeVuDlCbqxehBMdbtMA +Z74LhilPklqgvF36p3l3PIqO4427Rg49m5KxiBttoofq3nYFikrYPnVY1mYFnhSl +hwZG/eXLpRaYb/yDGdzHxzsQFYjxD3InLSfvd67fRG/T5+R8M5bDs+IZCFlGFvG/ +fA0uGH0fKEPUy7Ijex9cXag= +-----END PRIVATE KEY----- diff --git a/tests/keys/README.md b/tests/keys/README.md new file mode 100644 index 00000000..440a256a --- /dev/null +++ b/tests/keys/README.md @@ -0,0 +1,8 @@ +This are TEST keys, used for development purposes. + +You can install this keys on a VM EFI and test secureboot. + +They are pregenerated so you can iterate building Kairos UKI EFI and use the same signature without generating keys +all the time. + +They should never be installed anywhere different than a VM. \ No newline at end of file diff --git a/tests/tests_suite_test.go b/tests/tests_suite_test.go index de5675ed..ef79d4a0 100644 --- a/tests/tests_suite_test.go +++ b/tests/tests_suite_test.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path" + "path/filepath" "strconv" "testing" "time" @@ -103,6 +104,7 @@ func gatherLogs(vm VM) { "/run/immucore/immucore.log", "/run/immucore/initramfs_stage.log", "/run/immucore/rootfs_stage.log", + "/tmp/ovmf_debug.log", }) } @@ -191,24 +193,24 @@ func startVM() (context.Context, VM) { func(m *types.MachineConfig) error { FW := os.Getenv("FIRMWARE") if FW != "" { - m.Args = append(m.Args, - "-bios", FW) + getwd, err := os.Getwd() + if err != nil { + return err + } + m.Args = append(m.Args, "-drive", + fmt.Sprintf("file=%s,if=pflash,format=raw,readonly=on", FW), + ) + + // Set custom vars file for efi config so we boot first from disk then from DVD + m.Args = append(m.Args, "-drive", + fmt.Sprintf("file=%s,if=pflash,format=raw", filepath.Join(getwd, "assets/efivars.fd")), + ) + // Needed to be set for secureboot! + m.Args = append(m.Args, "-machine", "q35,smm=on") } return nil }, - // UKI boot - func(m *types.MachineConfig) error { - drive := os.Getenv("UKI_DRIVE") - // UKI drive needs to be set with bootindex=0 to be able to boot from that disk directly - // Otherwise it won't boot - if drive != "" { - m.Args = append(m.Args, - "-drive", fmt.Sprintf("file=%s,if=none,index=0,media=disk,format=raw,id=disk1", drive), - "-device", "virtio-blk-pci,drive=disk1,bootindex=0") - } - return nil - }, types.WithDataSource(os.Getenv("DATASOURCE")), } if os.Getenv("KVM") != "" { diff --git a/tests/uki_test.go b/tests/uki_test.go index 1ea9df4e..c5fca13c 100644 --- a/tests/uki_test.go +++ b/tests/uki_test.go @@ -13,9 +13,6 @@ var _ = Describe("kairos UKI test", Label("uki"), Ordered, func() { var vm VM BeforeAll(func() { - if os.Getenv("UKI_DRIVE") == "" { - Fail("UKI_DRIVE environment variable set to a UKI disk is needed for UKI test") - } if os.Getenv("FIRMWARE") == "" { Fail("FIRMWARE environment variable set to a EFI firmware is needed for UKI test") } @@ -23,7 +20,7 @@ var _ = Describe("kairos UKI test", Label("uki"), Ordered, func() { BeforeEach(func() { _, vm = startVM() - vm.EventuallyConnects(1200) + vm.EventuallyConnects(300) }) AfterEach(func() { @@ -35,6 +32,49 @@ var _ = Describe("kairos UKI test", Label("uki"), Ordered, func() { Expect(err).ToNot(HaveOccurred()) }) It("passes checks", func() { + By("Checking SecureBoot is enabled", func() { + out, err := vm.Sudo(`dmesg|grep -i secure| grep -i enabled`) + Expect(err).ToNot(HaveOccurred(), out) + }) + By("Checking the boot mode (install)", func() { + out, err := vm.Sudo("stat /run/cos/uki_install_mode") + Expect(err).ToNot(HaveOccurred(), out) + }) + By("Checking OEM/PERSISTENT are not mounted", func() { + out, err := vm.Sudo("mount") + Expect(err).ToNot(HaveOccurred()) + Expect(out).ToNot(ContainSubstring("/dev/disk/by-label/COS_OEM")) + Expect(out).ToNot(ContainSubstring("/dev/disk/by-label/COS_PERSISTENT")) + }) + By("installing kairos", func() { + out, err := vm.Sudo(`kairos-agent --debug uki install --device /dev/vda`) + Expect(err).ToNot(HaveOccurred(), out) + Expect(out).Should(ContainSubstring("Running after-install hook")) + vm.Sudo("sync") + }) + + By("Ejecting Cdrom", func() { + vm.DetachCD() + }) + + By("waiting for VM to reboot", func() { + vm.Reboot() + vm.EventuallyConnects(1200) + }) + By("Checking the boot mode (boot)", func() { + out, err := vm.Sudo("stat /run/cos/uki_boot_mode") + Expect(err).ToNot(HaveOccurred(), out) + }) + By("Checking SecureBoot is enabled", func() { + out, err := vm.Sudo(`dmesg|grep -i secure| grep -i enabled`) + Expect(err).ToNot(HaveOccurred(), out) + }) + By("Checking OEM/PERSISTENT are mounted", func() { + out, err := vm.Sudo("df -h") // Shows the disk by label which is easier to check + Expect(err).ToNot(HaveOccurred()) + Expect(out).To(ContainSubstring("/dev/disk/by-label/COS_OEM")) + Expect(out).To(ContainSubstring("/dev/disk/by-label/COS_PERSISTENT")) + }) By("checking custom cmdline", func() { out, err := vm.Sudo("cat /proc/cmdline") @@ -81,7 +121,7 @@ var _ = Describe("kairos UKI test", Label("uki"), Ordered, func() { By("checking corresponding state", func() { out, err := vm.Sudo("kairos-agent state") Expect(err).ToNot(HaveOccurred()) - // TODO: make agetn report uki_mode or something? + // TODO: make agent report uki_mode or something? Expect(out).To(ContainSubstring("boot: unknown")) currentVersion, err := vm.Sudo(getVersionCmd) Expect(err).ToNot(HaveOccurred(), currentVersion) diff --git a/tests/upgrade_cli_test.go b/tests/upgrade_cli_test.go index df177511..05f46213 100644 --- a/tests/upgrade_cli_test.go +++ b/tests/upgrade_cli_test.go @@ -47,8 +47,6 @@ var _ = Describe("k3s upgrade manual test", Label("upgrade-with-cli"), func() { Expect(out).Should(ContainSubstring("Running after-install hook")) vm.Sudo("sync") - err = vm.DetachCD() - Expect(err).ToNot(HaveOccurred()) By("Rebooting") vm.Reboot() }) diff --git a/tests/upgrade_latest_cli_test.go b/tests/upgrade_latest_cli_test.go index 38bcf53e..587d38b2 100644 --- a/tests/upgrade_latest_cli_test.go +++ b/tests/upgrade_latest_cli_test.go @@ -48,8 +48,6 @@ var _ = Describe("k3s upgrade manual test", Label("upgrade-latest-with-cli"), fu Expect(installOutput).Should(ContainSubstring("Running after-install hook")) vm.Sudo("sync") - err = vm.DetachCD() - Expect(err).ToNot(HaveOccurred()) By("Rebooting") vm.Reboot() }) diff --git a/tests/zfs_test.go b/tests/zfs_test.go index 86a71bd3..62a3da16 100644 --- a/tests/zfs_test.go +++ b/tests/zfs_test.go @@ -28,8 +28,7 @@ var _ = Describe("kairos zfs test", Label("zfs"), func() { Expect(err).ToNot(HaveOccurred(), out) out, err = vm.Sudo("sync") Expect(err).ToNot(HaveOccurred(), out) - err = vm.DetachCD() - Expect(err).ToNot(HaveOccurred()) + vm.Reboot() })