From 05ed54115ff77d1a55791c5ac439161605cdfec3 Mon Sep 17 00:00:00 2001 From: Itxaka Date: Tue, 3 Oct 2023 22:00:55 +0200 Subject: [PATCH] Improve uki iso stuff (#1854) --- .github/workflows/uki.yaml | 60 ++++++++++ Earthfile | 182 ++++++++++++++----------------- tests/assets/efivars.fd | Bin 0 -> 131072 bytes tests/assets/efivars.json | 165 ++++++++++++++++++++++++++++ tests/assets/efivars.md | 18 +++ tests/go.mod | 5 +- tests/go.sum | 8 ++ tests/keys/DB.crt | 19 ++++ tests/keys/DB.der | Bin 0 -> 781 bytes tests/keys/DB.key | 28 +++++ tests/keys/KEK.crt | 19 ++++ tests/keys/KEK.der | Bin 0 -> 783 bytes tests/keys/KEK.key | 28 +++++ tests/keys/PK.crt | 19 ++++ tests/keys/PK.der | Bin 0 -> 781 bytes tests/keys/PK.key | 28 +++++ tests/keys/README.md | 8 ++ tests/tests_suite_test.go | 30 ++--- tests/uki_test.go | 50 ++++++++- tests/upgrade_cli_test.go | 2 - tests/upgrade_latest_cli_test.go | 2 - tests/zfs_test.go | 3 +- 22 files changed, 548 insertions(+), 126 deletions(-) create mode 100644 .github/workflows/uki.yaml create mode 100644 tests/assets/efivars.fd create mode 100644 tests/assets/efivars.json create mode 100644 tests/assets/efivars.md create mode 100644 tests/keys/DB.crt create mode 100644 tests/keys/DB.der create mode 100644 tests/keys/DB.key create mode 100644 tests/keys/KEK.crt create mode 100644 tests/keys/KEK.der create mode 100644 tests/keys/KEK.key create mode 100644 tests/keys/PK.crt create mode 100644 tests/keys/PK.der create mode 100644 tests/keys/PK.key create mode 100644 tests/keys/README.md 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 0000000000000000000000000000000000000000..1f99259ce0c14a7364264a70b5b43ab4af6fcf6c GIT binary patch literal 131072 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 Qs#sgcr-?sLOrF;Y08#5lTmS$7 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..1a01f4e3567210bf27e8957491c330560c4c389d GIT binary patch literal 783 zcmXqLV&*nzV*I>-nTe5!Nkqgm+_A}5|MD`kPV+gNdZP`F9D8cO%f_kI=F#?@mywa1 zmBB#NP}o3_jX9KsnTN|eF|#PYSi#%X+dxj7*T~qw(#X`%(!|2VG)kP;7{oP#a&c*E zVpKx5fRUAfxrvdV0q7}?pc+r7*ckea+J$o;7wArm##Vj$m?61?Bms;^AMHjY|n3-+S4lzC2 zbbsyE)eASSpL{8@;?;sXcj`8NJDVIN*daPYWhVcuIJ*du8fCs)hKFarRp)>Ce%Isb zwj-P8v#$5jUl;J~=F4xBW=!2%GNCl5=-Q-%+e4&Uzr{bYTHr9ZocWcAyWGoWEuL)c zw_%1mrtD6c@N=jBq;RFgw#%hYdY&&Va$4aiZ?k}N;dz5w+wU#<9WQHm_qcn8N_hXn zSkCiy7v|R#gg)E5Ytr%^S{;Xu-+FYursY)h8KaAqOw5c7jEjQ}0u5w=VJ^$ZBE}+O z^XsGbtL|s=y^_omJv;3;Cu~UCVjvHaR%Vef5Np7$fFGnln33^63#$P$kU|c2V7vl@ zosq#{ljW*p!{-jMR$f6&MzU55cV74Mxqo?$;y#bmU#U|Jgr;se82G~Wjoi7H=ZX`J zydp%`C%+Q2c=+SW@6{=ei)D)KPgxu|wPdFMjHXk&bh0x$n8G*SSs=Mm!}r^9hRp)) z<)(B0sMrLGWh_>(j^*^$lo#)r|M;bhMamv=7wxrnIeZ7xv~BaVninZ(ytq}^d)0fw zfzY!T7pzF`fov%jzZ$Iz+ zQ%(2NUzOW?%G(XEvnPcA-6D2bT~6w&^Y*WQvQ|IU-Mqc%Z^RyTALG@!cdw-1Q9X1k S@Z{Ul%UhzdcvStW9|8b(97Zw# literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..97b65b5c1456d3bb86971b80e4bb9b09244d6a66 GIT binary patch literal 781 zcmXqLV&*hxV*I#(nTe5!Nu**)rkmsYWC8hltNVxVa(+0V>SJWU%f_kI=F#?@mywa1 zmBB#7P{=@ljX9KsnTOLmF|#PYSRugMKu(<3$k@Qr$kfo%#KOoTN}Sgi#5IC)ap-Dd zR6;hMk(GhDiIJZH=prtrCPqevm0v&p+o^KZ_@-~h8i&Y-Zu^2i-RpR#U#wkl?x#!k zCcdff-xY5;uUC3DFo-vF?oCOT%UszOqATid)+~H-)IFfM_0MD5G8h?&+xZkAUE!6O)WyLhNY;#e&Nq?O8R2)54;rWL1RNJLz@7Esfcj^Af@YrJ^ zv&@{NjEsPy(}%46zPt_5{QpZf_f(U!#1igV(>5iS?^U>%EqW=?EkJR{x+yK@3!X2J z`z#)_Gf<&v(+$JrMU#vkxK0r)7STvPy~bw0)0HU!%t>}LKUeWv*nd0zR8H;19(i%? zrngt;mZs^oNHuXTz2Y@Hdb{37-5bZk4#>|6SkJ`F$iTQb*dWkA78v5Pd@N!tBJ!3Q z4tMsuTs-?eNO8WK)Nzj3q8$eEAZcY52?MbP>4;{ThE-uxGK@-X6*b`9OxyXl_K z2Z?QI%ft)!-M$vR+?M(NvXb*B*>n$7