xref: /openbmc/qemu/tests/qemu-iotests/149 (revision ae50b71db01df0bb0b39694ab12354b80c9c95df)
108db36f6SFam Zheng#!/usr/bin/env python
26278ae03SDaniel P. Berrange#
36278ae03SDaniel P. Berrange# Copyright (C) 2016 Red Hat, Inc.
46278ae03SDaniel P. Berrange#
56278ae03SDaniel P. Berrange# This program is free software; you can redistribute it and/or modify
66278ae03SDaniel P. Berrange# it under the terms of the GNU General Public License as published by
76278ae03SDaniel P. Berrange# the Free Software Foundation; either version 2 of the License, or
86278ae03SDaniel P. Berrange# (at your option) any later version.
96278ae03SDaniel P. Berrange#
106278ae03SDaniel P. Berrange# This program is distributed in the hope that it will be useful,
116278ae03SDaniel P. Berrange# but WITHOUT ANY WARRANTY; without even the implied warranty of
126278ae03SDaniel P. Berrange# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
136278ae03SDaniel P. Berrange# GNU General Public License for more details.
146278ae03SDaniel P. Berrange#
156278ae03SDaniel P. Berrange# You should have received a copy of the GNU General Public License
166278ae03SDaniel P. Berrange# along with this program.  If not, see <http://www.gnu.org/licenses/>.
176278ae03SDaniel P. Berrange#
186278ae03SDaniel P. Berrange# Creator/Owner: Daniel P. Berrange <berrange@redhat.com>
196278ae03SDaniel P. Berrange#
206278ae03SDaniel P. Berrange# Exercise the QEMU 'luks' block driver to validate interoperability
216278ae03SDaniel P. Berrange# with the Linux dm-crypt + cryptsetup implementation
226278ae03SDaniel P. Berrange
236278ae03SDaniel P. Berrangeimport subprocess
246278ae03SDaniel P. Berrangeimport os
256278ae03SDaniel P. Berrangeimport os.path
266278ae03SDaniel P. Berrange
276278ae03SDaniel P. Berrangeimport base64
286278ae03SDaniel P. Berrange
296278ae03SDaniel P. Berrangeimport iotests
306278ae03SDaniel P. Berrange
316278ae03SDaniel P. Berrange
326278ae03SDaniel P. Berrangeclass LUKSConfig(object):
336278ae03SDaniel P. Berrange    """Represent configuration parameters for a single LUKS
346278ae03SDaniel P. Berrange       setup to be tested"""
356278ae03SDaniel P. Berrange
366278ae03SDaniel P. Berrange    def __init__(self, name, cipher, keylen, mode, ivgen,
376278ae03SDaniel P. Berrange                 ivgen_hash, hash, password=None, passwords=None):
386278ae03SDaniel P. Berrange
396278ae03SDaniel P. Berrange        self.name = name
406278ae03SDaniel P. Berrange        self.cipher = cipher
416278ae03SDaniel P. Berrange        self.keylen = keylen
426278ae03SDaniel P. Berrange        self.mode = mode
436278ae03SDaniel P. Berrange        self.ivgen = ivgen
446278ae03SDaniel P. Berrange        self.ivgen_hash = ivgen_hash
456278ae03SDaniel P. Berrange        self.hash = hash
466278ae03SDaniel P. Berrange
476278ae03SDaniel P. Berrange        if passwords is not None:
486278ae03SDaniel P. Berrange            self.passwords = passwords
496278ae03SDaniel P. Berrange        else:
506278ae03SDaniel P. Berrange            self.passwords = {}
516278ae03SDaniel P. Berrange
526278ae03SDaniel P. Berrange            if password is None:
536278ae03SDaniel P. Berrange                self.passwords["0"] = "123456"
546278ae03SDaniel P. Berrange            else:
556278ae03SDaniel P. Berrange                self.passwords["0"] = password
566278ae03SDaniel P. Berrange
576278ae03SDaniel P. Berrange    def __repr__(self):
586278ae03SDaniel P. Berrange        return self.name
596278ae03SDaniel P. Berrange
606278ae03SDaniel P. Berrange    def image_name(self):
616278ae03SDaniel P. Berrange        return "luks-%s.img" % self.name
626278ae03SDaniel P. Berrange
636278ae03SDaniel P. Berrange    def image_path(self):
646278ae03SDaniel P. Berrange        return os.path.join(iotests.test_dir, self.image_name())
656278ae03SDaniel P. Berrange
666278ae03SDaniel P. Berrange    def device_name(self):
676278ae03SDaniel P. Berrange        return "qiotest-145-%s" % self.name
686278ae03SDaniel P. Berrange
696278ae03SDaniel P. Berrange    def device_path(self):
706278ae03SDaniel P. Berrange        return "/dev/mapper/" + self.device_name()
716278ae03SDaniel P. Berrange
726278ae03SDaniel P. Berrange    def first_password(self):
736278ae03SDaniel P. Berrange        for i in range(8):
746278ae03SDaniel P. Berrange            slot = str(i)
756278ae03SDaniel P. Berrange            if slot in self.passwords:
766278ae03SDaniel P. Berrange                return (self.passwords[slot], slot)
776278ae03SDaniel P. Berrange        raise Exception("No password found")
786278ae03SDaniel P. Berrange
796278ae03SDaniel P. Berrange    def first_password_base64(self):
806278ae03SDaniel P. Berrange        (pw, slot) = self.first_password()
816278ae03SDaniel P. Berrange        return base64.b64encode(pw)
826278ae03SDaniel P. Berrange
836278ae03SDaniel P. Berrange    def active_slots(self):
846278ae03SDaniel P. Berrange        slots = []
856278ae03SDaniel P. Berrange        for i in range(8):
866278ae03SDaniel P. Berrange            slot = str(i)
876278ae03SDaniel P. Berrange            if slot in self.passwords:
886278ae03SDaniel P. Berrange                slots.append(slot)
896278ae03SDaniel P. Berrange        return slots
906278ae03SDaniel P. Berrange
916278ae03SDaniel P. Berrangedef verify_passwordless_sudo():
926278ae03SDaniel P. Berrange    """Check whether sudo is configured to allow
936278ae03SDaniel P. Berrange       password-less access to commands"""
946278ae03SDaniel P. Berrange
956278ae03SDaniel P. Berrange    args = ["sudo", "-n", "/bin/true"]
966278ae03SDaniel P. Berrange
976278ae03SDaniel P. Berrange    proc = subprocess.Popen(args,
986278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
996278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
1006278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
1016278ae03SDaniel P. Berrange
1026278ae03SDaniel P. Berrange    msg = proc.communicate()[0]
1036278ae03SDaniel P. Berrange
1046278ae03SDaniel P. Berrange    if proc.returncode != 0:
1056278ae03SDaniel P. Berrange        iotests.notrun('requires password-less sudo access: %s' % msg)
1066278ae03SDaniel P. Berrange
1076278ae03SDaniel P. Berrange
1086278ae03SDaniel P. Berrangedef cryptsetup(args, password=None):
1096278ae03SDaniel P. Berrange    """Run the cryptsetup command in batch mode"""
1106278ae03SDaniel P. Berrange
1116278ae03SDaniel P. Berrange    fullargs = ["sudo", "cryptsetup", "-q", "-v"]
1126278ae03SDaniel P. Berrange    fullargs.extend(args)
1136278ae03SDaniel P. Berrange
1146278ae03SDaniel P. Berrange    iotests.log(" ".join(fullargs), filters=[iotests.filter_test_dir])
1156278ae03SDaniel P. Berrange    proc = subprocess.Popen(fullargs,
1166278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
1176278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
1186278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
1196278ae03SDaniel P. Berrange
1206278ae03SDaniel P. Berrange    msg = proc.communicate(password)[0]
1216278ae03SDaniel P. Berrange
1226278ae03SDaniel P. Berrange    if proc.returncode != 0:
1236278ae03SDaniel P. Berrange        raise Exception(msg)
1246278ae03SDaniel P. Berrange
1256278ae03SDaniel P. Berrange
1266278ae03SDaniel P. Berrangedef cryptsetup_add_password(config, slot):
1276278ae03SDaniel P. Berrange    """Add another password to a LUKS key slot"""
1286278ae03SDaniel P. Berrange
1296278ae03SDaniel P. Berrange    (password, mainslot) = config.first_password()
1306278ae03SDaniel P. Berrange
1316278ae03SDaniel P. Berrange    pwfile = os.path.join(iotests.test_dir, "passwd.txt")
1326278ae03SDaniel P. Berrange    with open(pwfile, "w") as fh:
1336278ae03SDaniel P. Berrange        fh.write(config.passwords[slot])
1346278ae03SDaniel P. Berrange
1356278ae03SDaniel P. Berrange    try:
1366278ae03SDaniel P. Berrange        args = ["luksAddKey", config.image_path(),
1376278ae03SDaniel P. Berrange                "--key-slot", slot,
1386278ae03SDaniel P. Berrange                "--key-file", "-",
139307d9991SDaniel P. Berrange                "--iter-time", "10",
1406278ae03SDaniel P. Berrange                pwfile]
1416278ae03SDaniel P. Berrange
1426278ae03SDaniel P. Berrange        cryptsetup(args, password)
1436278ae03SDaniel P. Berrange    finally:
1446278ae03SDaniel P. Berrange        os.unlink(pwfile)
1456278ae03SDaniel P. Berrange
1466278ae03SDaniel P. Berrange
1476278ae03SDaniel P. Berrangedef cryptsetup_format(config):
1486278ae03SDaniel P. Berrange    """Format a new LUKS volume with cryptsetup, adding the
1496278ae03SDaniel P. Berrange    first key slot only"""
1506278ae03SDaniel P. Berrange
1516278ae03SDaniel P. Berrange    (password, slot) = config.first_password()
1526278ae03SDaniel P. Berrange
1536278ae03SDaniel P. Berrange    args = ["luksFormat"]
1546278ae03SDaniel P. Berrange    cipher = config.cipher + "-" + config.mode + "-" + config.ivgen
1556278ae03SDaniel P. Berrange    if config.ivgen_hash is not None:
1566278ae03SDaniel P. Berrange        cipher = cipher + ":" + config.ivgen_hash
1578b7cdba3SDaniel P. Berrange    elif config.ivgen == "essiv":
1588b7cdba3SDaniel P. Berrange        cipher = cipher + ":" + "sha256"
1596278ae03SDaniel P. Berrange    args.extend(["--cipher", cipher])
1606278ae03SDaniel P. Berrange    if config.mode == "xts":
1616278ae03SDaniel P. Berrange        args.extend(["--key-size", str(config.keylen * 2)])
1626278ae03SDaniel P. Berrange    else:
1636278ae03SDaniel P. Berrange        args.extend(["--key-size", str(config.keylen)])
1646278ae03SDaniel P. Berrange    if config.hash is not None:
1656278ae03SDaniel P. Berrange        args.extend(["--hash", config.hash])
1666278ae03SDaniel P. Berrange    args.extend(["--key-slot", slot])
1676278ae03SDaniel P. Berrange    args.extend(["--key-file", "-"])
168307d9991SDaniel P. Berrange    args.extend(["--iter-time", "10"])
1696278ae03SDaniel P. Berrange    args.append(config.image_path())
1706278ae03SDaniel P. Berrange
1716278ae03SDaniel P. Berrange    cryptsetup(args, password)
1726278ae03SDaniel P. Berrange
1736278ae03SDaniel P. Berrange
1746278ae03SDaniel P. Berrangedef chown(config):
1756278ae03SDaniel P. Berrange    """Set the ownership of a open LUKS device to this user"""
1766278ae03SDaniel P. Berrange
1776278ae03SDaniel P. Berrange    path = config.device_path()
1786278ae03SDaniel P. Berrange
1796278ae03SDaniel P. Berrange    args = ["sudo", "chown", "%d:%d" % (os.getuid(), os.getgid()), path]
1806278ae03SDaniel P. Berrange    iotests.log(" ".join(args), filters=[iotests.filter_chown])
1816278ae03SDaniel P. Berrange    proc = subprocess.Popen(args,
1826278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
1836278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
1846278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
1856278ae03SDaniel P. Berrange
1866278ae03SDaniel P. Berrange    msg = proc.communicate()[0]
1876278ae03SDaniel P. Berrange
1886278ae03SDaniel P. Berrange    if proc.returncode != 0:
189*ae50b71dSDaniel P. Berrange        raise Exception(msg)
1906278ae03SDaniel P. Berrange
1916278ae03SDaniel P. Berrange
1926278ae03SDaniel P. Berrangedef cryptsetup_open(config):
1936278ae03SDaniel P. Berrange    """Open an image as a LUKS device"""
1946278ae03SDaniel P. Berrange
1956278ae03SDaniel P. Berrange    (password, slot) = config.first_password()
1966278ae03SDaniel P. Berrange
1976278ae03SDaniel P. Berrange    args = ["luksOpen", config.image_path(), config.device_name()]
1986278ae03SDaniel P. Berrange
1996278ae03SDaniel P. Berrange    cryptsetup(args, password)
2006278ae03SDaniel P. Berrange
2016278ae03SDaniel P. Berrange
2026278ae03SDaniel P. Berrangedef cryptsetup_close(config):
2036278ae03SDaniel P. Berrange    """Close an active LUKS device """
2046278ae03SDaniel P. Berrange
2056278ae03SDaniel P. Berrange    args = ["luksClose", config.device_name()]
2066278ae03SDaniel P. Berrange    cryptsetup(args)
2076278ae03SDaniel P. Berrange
2086278ae03SDaniel P. Berrange
2096278ae03SDaniel P. Berrangedef delete_image(config):
2106278ae03SDaniel P. Berrange    """Delete a disk image"""
2116278ae03SDaniel P. Berrange
2126278ae03SDaniel P. Berrange    try:
2136278ae03SDaniel P. Berrange        os.unlink(config.image_path())
2146278ae03SDaniel P. Berrange        iotests.log("unlink %s" % config.image_path(),
2156278ae03SDaniel P. Berrange                    filters=[iotests.filter_test_dir])
2166278ae03SDaniel P. Berrange    except Exception as e:
2176278ae03SDaniel P. Berrange        pass
2186278ae03SDaniel P. Berrange
2196278ae03SDaniel P. Berrange
2206278ae03SDaniel P. Berrangedef create_image(config, size_mb):
2216278ae03SDaniel P. Berrange    """Create a bare disk image with requested size"""
2226278ae03SDaniel P. Berrange
2236278ae03SDaniel P. Berrange    delete_image(config)
2246278ae03SDaniel P. Berrange    iotests.log("truncate %s --size %dMB" % (config.image_path(), size_mb),
2256278ae03SDaniel P. Berrange                filters=[iotests.filter_test_dir])
2266278ae03SDaniel P. Berrange    with open(config.image_path(), "w") as fn:
2276278ae03SDaniel P. Berrange        fn.truncate(size_mb * 1024 * 1024)
2286278ae03SDaniel P. Berrange
2296278ae03SDaniel P. Berrange
2306278ae03SDaniel P. Berrangedef qemu_img_create(config, size_mb):
2316278ae03SDaniel P. Berrange    """Create and format a disk image with LUKS using qemu-img"""
2326278ae03SDaniel P. Berrange
2336278ae03SDaniel P. Berrange    opts = [
2346278ae03SDaniel P. Berrange        "key-secret=sec0",
235307d9991SDaniel P. Berrange        "iter-time=10",
2366278ae03SDaniel P. Berrange        "cipher-alg=%s-%d" % (config.cipher, config.keylen),
2376278ae03SDaniel P. Berrange        "cipher-mode=%s" % config.mode,
2386278ae03SDaniel P. Berrange        "ivgen-alg=%s" % config.ivgen,
2396278ae03SDaniel P. Berrange        "hash-alg=%s" % config.hash,
2406278ae03SDaniel P. Berrange    ]
2416278ae03SDaniel P. Berrange    if config.ivgen_hash is not None:
2426278ae03SDaniel P. Berrange        opts.append("ivgen-hash-alg=%s" % config.ivgen_hash)
2436278ae03SDaniel P. Berrange
2446278ae03SDaniel P. Berrange    args = ["create", "-f", "luks",
2456278ae03SDaniel P. Berrange            "--object",
2466278ae03SDaniel P. Berrange            ("secret,id=sec0,data=%s,format=base64" %
2476278ae03SDaniel P. Berrange             config.first_password_base64()),
2486278ae03SDaniel P. Berrange            "-o", ",".join(opts),
2496278ae03SDaniel P. Berrange            config.image_path(),
2506278ae03SDaniel P. Berrange            "%dM" % size_mb]
2516278ae03SDaniel P. Berrange
2526278ae03SDaniel P. Berrange    iotests.log("qemu-img " + " ".join(args), filters=[iotests.filter_test_dir])
2536278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_img_pipe(*args), filters=[iotests.filter_test_dir])
2546278ae03SDaniel P. Berrange
2556278ae03SDaniel P. Berrangedef qemu_io_image_args(config, dev=False):
2566278ae03SDaniel P. Berrange    """Get the args for access an image or device with qemu-io"""
2576278ae03SDaniel P. Berrange
2586278ae03SDaniel P. Berrange    if dev:
2596278ae03SDaniel P. Berrange        return [
2606278ae03SDaniel P. Berrange            "--image-opts",
2616278ae03SDaniel P. Berrange            "driver=file,filename=%s" % config.device_path()]
2626278ae03SDaniel P. Berrange    else:
2636278ae03SDaniel P. Berrange        return [
2646278ae03SDaniel P. Berrange            "--object",
2656278ae03SDaniel P. Berrange            ("secret,id=sec0,data=%s,format=base64" %
2666278ae03SDaniel P. Berrange             config.first_password_base64()),
2676278ae03SDaniel P. Berrange            "--image-opts",
2686278ae03SDaniel P. Berrange            ("driver=luks,key-secret=sec0,file.filename=%s" %
2696278ae03SDaniel P. Berrange             config.image_path())]
2706278ae03SDaniel P. Berrange
2716278ae03SDaniel P. Berrangedef qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
2726278ae03SDaniel P. Berrange    """Write a pattern of data to a LUKS image or device"""
2736278ae03SDaniel P. Berrange
274*ae50b71dSDaniel P. Berrange    if dev:
275*ae50b71dSDaniel P. Berrange        chown(config)
2766278ae03SDaniel P. Berrange    args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
2776278ae03SDaniel P. Berrange    args.extend(qemu_io_image_args(config, dev))
2786278ae03SDaniel P. Berrange    iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
2796278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
2806278ae03SDaniel P. Berrange                                                 iotests.filter_qemu_io])
2816278ae03SDaniel P. Berrange
2826278ae03SDaniel P. Berrange
2836278ae03SDaniel P. Berrangedef qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
2846278ae03SDaniel P. Berrange    """Read a pattern of data to a LUKS image or device"""
2856278ae03SDaniel P. Berrange
286*ae50b71dSDaniel P. Berrange    if dev:
287*ae50b71dSDaniel P. Berrange        chown(config)
2886278ae03SDaniel P. Berrange    args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
2896278ae03SDaniel P. Berrange    args.extend(qemu_io_image_args(config, dev))
2906278ae03SDaniel P. Berrange    iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
2916278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
2926278ae03SDaniel P. Berrange                                                 iotests.filter_qemu_io])
2936278ae03SDaniel P. Berrange
2946278ae03SDaniel P. Berrange
2956278ae03SDaniel P. Berrangedef test_once(config, qemu_img=False):
2966278ae03SDaniel P. Berrange    """Run the test with a desired LUKS configuration. Can either
2976278ae03SDaniel P. Berrange       use qemu-img for creating the initial volume, or cryptsetup,
2986278ae03SDaniel P. Berrange       in order to test interoperability in both directions"""
2996278ae03SDaniel P. Berrange
3006278ae03SDaniel P. Berrange    iotests.log("# ================= %s %s =================" % (
3016278ae03SDaniel P. Berrange        "qemu-img" if qemu_img else "dm-crypt", config))
3026278ae03SDaniel P. Berrange
3036278ae03SDaniel P. Berrange    oneKB = 1024
3046278ae03SDaniel P. Berrange    oneMB = oneKB * 1024
3056278ae03SDaniel P. Berrange    oneGB = oneMB * 1024
3066278ae03SDaniel P. Berrange    oneTB = oneGB * 1024
3076278ae03SDaniel P. Berrange
3086278ae03SDaniel P. Berrange    # 4 TB, so that we pass the 32-bit sector number boundary.
3096278ae03SDaniel P. Berrange    # Important for testing correctness of some IV generators
3106278ae03SDaniel P. Berrange    # The files are sparse, so not actually using this much space
3116278ae03SDaniel P. Berrange    image_size = 4 * oneTB
3126278ae03SDaniel P. Berrange    if qemu_img:
3136278ae03SDaniel P. Berrange        iotests.log("# Create image")
3146278ae03SDaniel P. Berrange        qemu_img_create(config, image_size / oneMB)
3156278ae03SDaniel P. Berrange    else:
3166278ae03SDaniel P. Berrange        iotests.log("# Create image")
3176278ae03SDaniel P. Berrange        create_image(config, image_size / oneMB)
3186278ae03SDaniel P. Berrange
3196278ae03SDaniel P. Berrange    lowOffsetMB = 100
3206278ae03SDaniel P. Berrange    highOffsetMB = 3 * oneTB / oneMB
3216278ae03SDaniel P. Berrange
3226278ae03SDaniel P. Berrange    try:
3236278ae03SDaniel P. Berrange        if not qemu_img:
3246278ae03SDaniel P. Berrange            iotests.log("# Format image")
3256278ae03SDaniel P. Berrange            cryptsetup_format(config)
3266278ae03SDaniel P. Berrange
3276278ae03SDaniel P. Berrange            for slot in config.active_slots()[1:]:
3286278ae03SDaniel P. Berrange                iotests.log("# Add password slot %s" % slot)
3296278ae03SDaniel P. Berrange                cryptsetup_add_password(config, slot)
3306278ae03SDaniel P. Berrange
3316278ae03SDaniel P. Berrange        # First we'll open the image using cryptsetup and write a
3326278ae03SDaniel P. Berrange        # known pattern of data that we'll then verify with QEMU
3336278ae03SDaniel P. Berrange
3346278ae03SDaniel P. Berrange        iotests.log("# Open dev")
3356278ae03SDaniel P. Berrange        cryptsetup_open(config)
3366278ae03SDaniel P. Berrange
3376278ae03SDaniel P. Berrange        try:
3386278ae03SDaniel P. Berrange            iotests.log("# Write test pattern 0xa7")
3396278ae03SDaniel P. Berrange            qemu_io_write_pattern(config, 0xa7, lowOffsetMB, 10, dev=True)
3406278ae03SDaniel P. Berrange            iotests.log("# Write test pattern 0x13")
3416278ae03SDaniel P. Berrange            qemu_io_write_pattern(config, 0x13, highOffsetMB, 10, dev=True)
3426278ae03SDaniel P. Berrange        finally:
3436278ae03SDaniel P. Berrange            iotests.log("# Close dev")
3446278ae03SDaniel P. Berrange            cryptsetup_close(config)
3456278ae03SDaniel P. Berrange
3466278ae03SDaniel P. Berrange        # Ok, now we're using QEMU to verify the pattern just
3476278ae03SDaniel P. Berrange        # written via dm-crypt
3486278ae03SDaniel P. Berrange
3496278ae03SDaniel P. Berrange        iotests.log("# Read test pattern 0xa7")
3506278ae03SDaniel P. Berrange        qemu_io_read_pattern(config, 0xa7, lowOffsetMB, 10, dev=False)
3516278ae03SDaniel P. Berrange        iotests.log("# Read test pattern 0x13")
3526278ae03SDaniel P. Berrange        qemu_io_read_pattern(config, 0x13, highOffsetMB, 10, dev=False)
3536278ae03SDaniel P. Berrange
3546278ae03SDaniel P. Berrange
3556278ae03SDaniel P. Berrange        # Write a new pattern to the image, which we'll later
3566278ae03SDaniel P. Berrange        # verify with dm-crypt
3576278ae03SDaniel P. Berrange        iotests.log("# Write test pattern 0x91")
3586278ae03SDaniel P. Berrange        qemu_io_write_pattern(config, 0x91, lowOffsetMB, 10, dev=False)
3596278ae03SDaniel P. Berrange        iotests.log("# Write test pattern 0x5e")
3606278ae03SDaniel P. Berrange        qemu_io_write_pattern(config, 0x5e, highOffsetMB, 10, dev=False)
3616278ae03SDaniel P. Berrange
3626278ae03SDaniel P. Berrange
3636278ae03SDaniel P. Berrange        # Now we're opening the image with dm-crypt once more
3646278ae03SDaniel P. Berrange        # and verifying what QEMU wrote, completing the circle
3656278ae03SDaniel P. Berrange        iotests.log("# Open dev")
3666278ae03SDaniel P. Berrange        cryptsetup_open(config)
3676278ae03SDaniel P. Berrange
3686278ae03SDaniel P. Berrange        try:
3696278ae03SDaniel P. Berrange            iotests.log("# Read test pattern 0x91")
3706278ae03SDaniel P. Berrange            qemu_io_read_pattern(config, 0x91, lowOffsetMB, 10, dev=True)
3716278ae03SDaniel P. Berrange            iotests.log("# Read test pattern 0x5e")
3726278ae03SDaniel P. Berrange            qemu_io_read_pattern(config, 0x5e, highOffsetMB, 10, dev=True)
3736278ae03SDaniel P. Berrange        finally:
3746278ae03SDaniel P. Berrange            iotests.log("# Close dev")
3756278ae03SDaniel P. Berrange            cryptsetup_close(config)
3766278ae03SDaniel P. Berrange    finally:
3776278ae03SDaniel P. Berrange        iotests.log("# Delete image")
3786278ae03SDaniel P. Berrange        delete_image(config)
3796278ae03SDaniel P. Berrange        print
3806278ae03SDaniel P. Berrange
3816278ae03SDaniel P. Berrange
3826278ae03SDaniel P. Berrange# Obviously we only work with the luks image format
3836278ae03SDaniel P. Berrangeiotests.verify_image_format(supported_fmts=['luks'])
3846278ae03SDaniel P. Berrangeiotests.verify_platform()
3856278ae03SDaniel P. Berrange
3866278ae03SDaniel P. Berrange# We need sudo in order to run cryptsetup to create
3876278ae03SDaniel P. Berrange# dm-crypt devices. This is safe to use on any
3886278ae03SDaniel P. Berrange# machine, since all dm-crypt devices are backed
3896278ae03SDaniel P. Berrange# by newly created plain files, and have a dm-crypt
3906278ae03SDaniel P. Berrange# name prefix of 'qiotest' to avoid clashing with
3916278ae03SDaniel P. Berrange# user LUKS volumes
3926278ae03SDaniel P. Berrangeverify_passwordless_sudo()
3936278ae03SDaniel P. Berrange
3946278ae03SDaniel P. Berrange
3956278ae03SDaniel P. Berrange# If we look at all permutations of cipher, key size,
3966278ae03SDaniel P. Berrange# mode, ivgen, hash, there are ~1000 possible configs.
3976278ae03SDaniel P. Berrange#
3986278ae03SDaniel P. Berrange# We certainly don't want/need to test every permutation
3996278ae03SDaniel P. Berrange# to get good validation of interoperability between QEMU
4006278ae03SDaniel P. Berrange# and dm-crypt/cryptsetup.
4016278ae03SDaniel P. Berrange#
4026278ae03SDaniel P. Berrange# The configs below are a representative set that aim to
4036278ae03SDaniel P. Berrange# exercise each axis of configurability.
4046278ae03SDaniel P. Berrange#
4056278ae03SDaniel P. Berrangeconfigs = [
4066278ae03SDaniel P. Berrange    # A common LUKS default
4076278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha1",
4086278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha1"),
4096278ae03SDaniel P. Berrange
4106278ae03SDaniel P. Berrange
4116278ae03SDaniel P. Berrange    # LUKS default but diff ciphers
4126278ae03SDaniel P. Berrange    LUKSConfig("twofish-256-xts-plain64-sha1",
4136278ae03SDaniel P. Berrange               "twofish", 256, "xts", "plain64", None, "sha1"),
4146278ae03SDaniel P. Berrange    LUKSConfig("serpent-256-xts-plain64-sha1",
4156278ae03SDaniel P. Berrange               "serpent", 256, "xts", "plain64", None, "sha1"),
4166278ae03SDaniel P. Berrange    # Should really be xts, but kernel doesn't support xts+cast5
4176278ae03SDaniel P. Berrange    # nor does it do essiv+cast5
4186278ae03SDaniel P. Berrange    LUKSConfig("cast5-128-cbc-plain64-sha1",
4196278ae03SDaniel P. Berrange               "cast5", 128, "cbc", "plain64", None, "sha1"),
4206278ae03SDaniel P. Berrange    LUKSConfig("cast6-256-xts-plain64-sha1",
4216278ae03SDaniel P. Berrange               "cast6", 256, "xts", "plain64", None, "sha1"),
4226278ae03SDaniel P. Berrange
4236278ae03SDaniel P. Berrange
4246278ae03SDaniel P. Berrange    # LUKS default but diff modes / ivgens
4256278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain-sha1",
4266278ae03SDaniel P. Berrange               "aes", 256, "cbc", "plain", None, "sha1"),
4276278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain64-sha1",
4286278ae03SDaniel P. Berrange               "aes", 256, "cbc", "plain64", None, "sha1"),
4296278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-essiv-sha256-sha1",
4306278ae03SDaniel P. Berrange               "aes", 256, "cbc", "essiv", "sha256", "sha1"),
4316278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-essiv-sha256-sha1",
4326278ae03SDaniel P. Berrange               "aes", 256, "xts", "essiv", "sha256", "sha1"),
4336278ae03SDaniel P. Berrange
4346278ae03SDaniel P. Berrange
4356278ae03SDaniel P. Berrange    # LUKS default but smaller key sizes
4366278ae03SDaniel P. Berrange    LUKSConfig("aes-128-xts-plain64-sha256-sha1",
4376278ae03SDaniel P. Berrange               "aes", 128, "xts", "plain64", None, "sha1"),
4386278ae03SDaniel P. Berrange    LUKSConfig("aes-192-xts-plain64-sha256-sha1",
4396278ae03SDaniel P. Berrange               "aes", 192, "xts", "plain64", None, "sha1"),
4406278ae03SDaniel P. Berrange
4416278ae03SDaniel P. Berrange    LUKSConfig("twofish-128-xts-plain64-sha1",
4426278ae03SDaniel P. Berrange               "twofish", 128, "xts", "plain64", None, "sha1"),
4436278ae03SDaniel P. Berrange    LUKSConfig("twofish-192-xts-plain64-sha1",
4446278ae03SDaniel P. Berrange               "twofish", 192, "xts", "plain64", None, "sha1"),
4456278ae03SDaniel P. Berrange
4466278ae03SDaniel P. Berrange    LUKSConfig("serpent-128-xts-plain64-sha1",
4476278ae03SDaniel P. Berrange               "serpent", 128, "xts", "plain64", None, "sha1"),
4486278ae03SDaniel P. Berrange    LUKSConfig("serpent-192-xts-plain64-sha1",
4496278ae03SDaniel P. Berrange               "serpent", 192, "xts", "plain64", None, "sha1"),
4506278ae03SDaniel P. Berrange
4516278ae03SDaniel P. Berrange    LUKSConfig("cast6-128-xts-plain64-sha1",
4526278ae03SDaniel P. Berrange               "cast6", 128, "xts", "plain", None, "sha1"),
4536278ae03SDaniel P. Berrange    LUKSConfig("cast6-192-xts-plain64-sha1",
4546278ae03SDaniel P. Berrange               "cast6", 192, "xts", "plain64", None, "sha1"),
4556278ae03SDaniel P. Berrange
4566278ae03SDaniel P. Berrange
4576278ae03SDaniel P. Berrange    # LUKS default but diff hash
458a488e71eSDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha224",
459a488e71eSDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha224"),
4606278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha256",
4616278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha256"),
462a488e71eSDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha384",
463a488e71eSDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha384"),
4646278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha512",
4656278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha512"),
4666278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-ripemd160",
4676278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "ripemd160"),
4686278ae03SDaniel P. Berrange
4696278ae03SDaniel P. Berrange    # Password in slot 3
4706278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain-sha1-pwslot3",
4716278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain", None, "sha1",
4726278ae03SDaniel P. Berrange               passwords={
4736278ae03SDaniel P. Berrange                   "3": "slot3",
4746278ae03SDaniel P. Berrange               }),
4756278ae03SDaniel P. Berrange
4766278ae03SDaniel P. Berrange    # Passwords in every slot
4776278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain-sha1-pwallslots",
4786278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain", None, "sha1",
4796278ae03SDaniel P. Berrange               passwords={
4806278ae03SDaniel P. Berrange                   "0": "slot1",
4816278ae03SDaniel P. Berrange                   "1": "slot1",
4826278ae03SDaniel P. Berrange                   "2": "slot2",
4836278ae03SDaniel P. Berrange                   "3": "slot3",
4846278ae03SDaniel P. Berrange                   "4": "slot4",
4856278ae03SDaniel P. Berrange                   "5": "slot5",
4866278ae03SDaniel P. Berrange                   "6": "slot6",
4876278ae03SDaniel P. Berrange                   "7": "slot7",
4886278ae03SDaniel P. Berrange               }),
4898b7cdba3SDaniel P. Berrange
4908b7cdba3SDaniel P. Berrange    # Check handling of default hash alg (sha256) with essiv
4918b7cdba3SDaniel P. Berrange    LUKSConfig("aes-256-cbc-essiv-auto-sha1",
4928b7cdba3SDaniel P. Berrange               "aes", 256, "cbc", "essiv", None, "sha1"),
4938b7cdba3SDaniel P. Berrange
4948b7cdba3SDaniel P. Berrange    # Check that a useless hash provided for 'plain64' iv gen
4958b7cdba3SDaniel P. Berrange    # is ignored and no error raised
4968b7cdba3SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain64-sha256-sha1",
4978b7cdba3SDaniel P. Berrange               "aes", 256, "cbc", "plain64", "sha256", "sha1"),
4988b7cdba3SDaniel P. Berrange
4996278ae03SDaniel P. Berrange]
5006278ae03SDaniel P. Berrange
5016278ae03SDaniel P. Berrangeblacklist = [
5026278ae03SDaniel P. Berrange    # We don't have a cast-6 cipher impl for QEMU yet
5036278ae03SDaniel P. Berrange    "cast6-256-xts-plain64-sha1",
5046278ae03SDaniel P. Berrange    "cast6-128-xts-plain64-sha1",
5056278ae03SDaniel P. Berrange    "cast6-192-xts-plain64-sha1",
5066278ae03SDaniel P. Berrange
5076278ae03SDaniel P. Berrange    # GCrypt doesn't support Twofish with 192 bit key
5086278ae03SDaniel P. Berrange    "twofish-192-xts-plain64-sha1",
5096278ae03SDaniel P. Berrange]
5106278ae03SDaniel P. Berrange
5116278ae03SDaniel P. Berrangewhitelist = []
5126278ae03SDaniel P. Berrangeif "LUKS_CONFIG" in os.environ:
5136278ae03SDaniel P. Berrange    whitelist = os.environ["LUKS_CONFIG"].split(",")
5146278ae03SDaniel P. Berrange
5156278ae03SDaniel P. Berrangefor config in configs:
5166278ae03SDaniel P. Berrange    if config.name in blacklist:
5176278ae03SDaniel P. Berrange        iotests.log("Skipping %s in blacklist" % config.name)
5186278ae03SDaniel P. Berrange        continue
5196278ae03SDaniel P. Berrange
5206278ae03SDaniel P. Berrange    if len(whitelist) > 0 and config.name not in whitelist:
5216278ae03SDaniel P. Berrange        iotests.log("Skipping %s not in whitelist" % config.name)
5226278ae03SDaniel P. Berrange        continue
5236278ae03SDaniel P. Berrange
5246278ae03SDaniel P. Berrange    test_once(config, qemu_img=False)
5256278ae03SDaniel P. Berrange
5266278ae03SDaniel P. Berrange    # XXX we should support setting passwords in a non-0
5276278ae03SDaniel P. Berrange    # key slot with 'qemu-img create' in future
5286278ae03SDaniel P. Berrange    (pw, slot) = config.first_password()
5296278ae03SDaniel P. Berrange    if slot == "0":
5306278ae03SDaniel P. Berrange        test_once(config, qemu_img=True)
531