1import os 2import subprocess 3 4import infra.basetest 5 6 7class TestCryptSetup(infra.basetest.BRTest): 8 # A specific configuration is needed for using cryptsetup: 9 # - A kernel config fragment enables all the parts needed for 10 # mounting a LUKS2 volume, 11 # - Enable OpenSSL for cryptsetup crypto backend library, 12 # - Enable e2fsprog for formatting a ext4 filesystem. 13 kern_frag = \ 14 infra.filepath("tests/package/test_cryptsetup/linux-cryptsetup.fragment") 15 config = \ 16 f""" 17 BR2_aarch64=y 18 BR2_TOOLCHAIN_EXTERNAL=y 19 BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0" 20 BR2_LINUX_KERNEL=y 21 BR2_LINUX_KERNEL_CUSTOM_VERSION=y 22 BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.75" 23 BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y 24 BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config" 25 BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{kern_frag}" 26 BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y 27 BR2_PACKAGE_CRYPTSETUP=y 28 BR2_PACKAGE_E2FSPROGS=y 29 BR2_PACKAGE_OPENSSL=y 30 BR2_TARGET_ROOTFS_CPIO=y 31 BR2_TARGET_ROOTFS_CPIO_GZIP=y 32 # BR2_TARGET_ROOTFS_TAR is not set 33 """ 34 35 def test_run(self): 36 disk_file = os.path.join(self.builddir, "images", "disk.img") 37 self.emulator.logfile.write(f"Creating disk image: {disk_file}") 38 subprocess.check_call( 39 ["dd", "if=/dev/urandom", f"of={disk_file}", "bs=1M", "count=20"], 40 stdout=self.emulator.logfile, 41 stderr=self.emulator.logfile) 42 43 img = os.path.join(self.builddir, "images", "rootfs.cpio.gz") 44 kern = os.path.join(self.builddir, "images", "Image") 45 46 bootargs = ["console=ttyAMA0"] 47 qemu_opts = ["-M", "virt", "-cpu", "cortex-a57", "-m", "256M", 48 "-initrd", img, 49 "-drive", f"file={disk_file},if=virtio,format=raw"] 50 self.emulator.boot(arch="aarch64", 51 kernel=kern, 52 kernel_cmdline=bootargs, 53 options=qemu_opts) 54 self.emulator.login() 55 56 # Check the program can execute. 57 self.assertRunOk("cryptsetup --version") 58 59 passkey = "ThisIsAPassKey." 60 dev = "/dev/vda" 61 dm_name = "luks-vol" 62 dm_dev = f"/dev/mapper/{dm_name}" 63 mnt_pt = "/mnt/secure-volume" 64 65 # Check the device is NOT detected as a LUKS volume, because 66 # it is not formatted yet. 67 is_luks_cmd = f"cryptsetup isLuks {dev}" 68 _, ret = self.emulator.run(is_luks_cmd) 69 self.assertNotEqual(ret, 0) 70 71 # Format the LUKS volume. 72 cmd = f"echo {passkey} | cryptsetup luksFormat {dev}" 73 self.assertRunOk(cmd, timeout=30) 74 75 # Check the device is now detected as a LUKS device. 76 self.assertRunOk(is_luks_cmd) 77 78 # Dump LUKS device header information. 79 self.assertRunOk(f"cryptsetup luksDump {dev}") 80 81 # Open the LUKS device 82 luks_open_cmd = f"echo {passkey} | " 83 luks_open_cmd += f"cryptsetup open --type luks {dev} {dm_name}" 84 self.assertRunOk(luks_open_cmd, timeout=10) 85 86 # Create an ext4 filesystem. 87 self.assertRunOk(f"mke2fs -T ext4 {dm_dev}", timeout=10) 88 89 # Create the mount point directory. 90 self.assertRunOk(f"mkdir {mnt_pt}") 91 92 # Mount the LUKS device. 93 mount_cmd = f"mount {dm_dev} {mnt_pt}" 94 self.assertRunOk(mount_cmd) 95 96 # Create a plain text file in the mounted filesystem. 97 msg = "This is a plain text message" 98 plain_file = f"{mnt_pt}/file.txt" 99 self.assertRunOk(f"echo '{msg}' > {plain_file}") 100 101 # Unmount. 102 self.assertRunOk(f"umount {mnt_pt}") 103 104 # We are supposed to see our plain text message on the 105 # dm-crypt device. 106 self.assertRunOk(f"grep -Fq '{msg}' {dm_dev}", timeout=10) 107 108 # Close the LUKS device 109 self.assertRunOk(f"cryptsetup close {dm_name}") 110 111 # We are NOT supposed to find our plain text message on the 112 # crypted storage device. 113 _, ret = self.emulator.run(f"grep -Fq '{msg}' {dev}", timeout=10) 114 self.assertNotEqual(ret, 0) 115 116 # Try to open LUKS volume with a wrong password. This is 117 # expected to fail. 118 cmd = f"echo 'Wrong{passkey}' | " 119 cmd += f"cryptsetup open --type luks {dev} {dm_name}" 120 _, ret = self.emulator.run(cmd, timeout=10) 121 self.assertNotEqual(ret, 0) 122 123 # Check the device-mapper device was NOT created (since we 124 # tried to open it with a wrong password). 125 self.assertRunOk(f"test ! -e {dm_dev}") 126 127 # Reopen the LUKS device, with the good passkey this time... 128 self.assertRunOk(luks_open_cmd, timeout=10) 129 130 # ...remount... 131 self.assertRunOk(mount_cmd) 132 133 # ...and read back our plain text file. We check we get back 134 # our original message. 135 out, ret = self.emulator.run(f"cat {plain_file}") 136 self.assertEqual(ret, 0) 137 self.assertEqual(out[0], msg) 138