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