xref: /openbmc/qemu/tests/qemu-iotests/149 (revision 7c4775260807f1428484a5cebc7bc360c46a872d)
1*7c477526SPhilippe Mathieu-Daudé#!/usr/bin/env python3
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
23f03868bdSEduardo 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()
828eb5e674SMax Reitz        return base64.b64encode(pw.encode('ascii')).decode('ascii')
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,
1018eb5e674SMax Reitz                            stderr=subprocess.STDOUT,
1028eb5e674SMax Reitz                            universal_newlines=True)
1036278ae03SDaniel P. Berrange
1046278ae03SDaniel P. Berrange    msg = proc.communicate()[0]
1056278ae03SDaniel P. Berrange
1066278ae03SDaniel P. Berrange    if proc.returncode != 0:
1076278ae03SDaniel P. Berrange        iotests.notrun('requires password-less sudo access: %s' % msg)
1086278ae03SDaniel P. Berrange
1096278ae03SDaniel P. Berrange
1106278ae03SDaniel P. Berrangedef cryptsetup(args, password=None):
1116278ae03SDaniel P. Berrange    """Run the cryptsetup command in batch mode"""
1126278ae03SDaniel P. Berrange
1136278ae03SDaniel P. Berrange    fullargs = ["sudo", "cryptsetup", "-q", "-v"]
1146278ae03SDaniel P. Berrange    fullargs.extend(args)
1156278ae03SDaniel P. Berrange
1166278ae03SDaniel P. Berrange    iotests.log(" ".join(fullargs), filters=[iotests.filter_test_dir])
1176278ae03SDaniel P. Berrange    proc = subprocess.Popen(fullargs,
1186278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
1196278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
1208eb5e674SMax Reitz                            stderr=subprocess.STDOUT,
1218eb5e674SMax Reitz                            universal_newlines=True)
1226278ae03SDaniel P. Berrange
1236278ae03SDaniel P. Berrange    msg = proc.communicate(password)[0]
1246278ae03SDaniel P. Berrange
1256278ae03SDaniel P. Berrange    if proc.returncode != 0:
1266278ae03SDaniel P. Berrange        raise Exception(msg)
1276278ae03SDaniel P. Berrange
1286278ae03SDaniel P. Berrange
1296278ae03SDaniel P. Berrangedef cryptsetup_add_password(config, slot):
1306278ae03SDaniel P. Berrange    """Add another password to a LUKS key slot"""
1316278ae03SDaniel P. Berrange
1326278ae03SDaniel P. Berrange    (password, mainslot) = config.first_password()
1336278ae03SDaniel P. Berrange
1346278ae03SDaniel P. Berrange    pwfile = os.path.join(iotests.test_dir, "passwd.txt")
1356278ae03SDaniel P. Berrange    with open(pwfile, "w") as fh:
1366278ae03SDaniel P. Berrange        fh.write(config.passwords[slot])
1376278ae03SDaniel P. Berrange
1386278ae03SDaniel P. Berrange    try:
1396278ae03SDaniel P. Berrange        args = ["luksAddKey", config.image_path(),
1406278ae03SDaniel P. Berrange                "--key-slot", slot,
1416278ae03SDaniel P. Berrange                "--key-file", "-",
142307d9991SDaniel P. Berrange                "--iter-time", "10",
1436278ae03SDaniel P. Berrange                pwfile]
1446278ae03SDaniel P. Berrange
1456278ae03SDaniel P. Berrange        cryptsetup(args, password)
1466278ae03SDaniel P. Berrange    finally:
1476278ae03SDaniel P. Berrange        os.unlink(pwfile)
1486278ae03SDaniel P. Berrange
1496278ae03SDaniel P. Berrange
1506278ae03SDaniel P. Berrangedef cryptsetup_format(config):
1516278ae03SDaniel P. Berrange    """Format a new LUKS volume with cryptsetup, adding the
1526278ae03SDaniel P. Berrange    first key slot only"""
1536278ae03SDaniel P. Berrange
1546278ae03SDaniel P. Berrange    (password, slot) = config.first_password()
1556278ae03SDaniel P. Berrange
156da51e998SDaniel P. Berrangé    args = ["luksFormat", "--type", "luks1"]
1576278ae03SDaniel P. Berrange    cipher = config.cipher + "-" + config.mode + "-" + config.ivgen
1586278ae03SDaniel P. Berrange    if config.ivgen_hash is not None:
1596278ae03SDaniel P. Berrange        cipher = cipher + ":" + config.ivgen_hash
1608b7cdba3SDaniel P. Berrange    elif config.ivgen == "essiv":
1618b7cdba3SDaniel P. Berrange        cipher = cipher + ":" + "sha256"
1626278ae03SDaniel P. Berrange    args.extend(["--cipher", cipher])
1636278ae03SDaniel P. Berrange    if config.mode == "xts":
1646278ae03SDaniel P. Berrange        args.extend(["--key-size", str(config.keylen * 2)])
1656278ae03SDaniel P. Berrange    else:
1666278ae03SDaniel P. Berrange        args.extend(["--key-size", str(config.keylen)])
1676278ae03SDaniel P. Berrange    if config.hash is not None:
1686278ae03SDaniel P. Berrange        args.extend(["--hash", config.hash])
1696278ae03SDaniel P. Berrange    args.extend(["--key-slot", slot])
1706278ae03SDaniel P. Berrange    args.extend(["--key-file", "-"])
171307d9991SDaniel P. Berrange    args.extend(["--iter-time", "10"])
1726278ae03SDaniel P. Berrange    args.append(config.image_path())
1736278ae03SDaniel P. Berrange
1746278ae03SDaniel P. Berrange    cryptsetup(args, password)
1756278ae03SDaniel P. Berrange
1766278ae03SDaniel P. Berrange
1776278ae03SDaniel P. Berrangedef chown(config):
1786278ae03SDaniel P. Berrange    """Set the ownership of a open LUKS device to this user"""
1796278ae03SDaniel P. Berrange
1806278ae03SDaniel P. Berrange    path = config.device_path()
1816278ae03SDaniel P. Berrange
1826278ae03SDaniel P. Berrange    args = ["sudo", "chown", "%d:%d" % (os.getuid(), os.getgid()), path]
1836278ae03SDaniel P. Berrange    iotests.log(" ".join(args), filters=[iotests.filter_chown])
1846278ae03SDaniel P. Berrange    proc = subprocess.Popen(args,
1856278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
1866278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
1876278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
1886278ae03SDaniel P. Berrange
1896278ae03SDaniel P. Berrange    msg = proc.communicate()[0]
1906278ae03SDaniel P. Berrange
1916278ae03SDaniel P. Berrange    if proc.returncode != 0:
192ae50b71dSDaniel P. Berrange        raise Exception(msg)
1936278ae03SDaniel P. Berrange
1946278ae03SDaniel P. Berrange
1956278ae03SDaniel P. Berrangedef cryptsetup_open(config):
1966278ae03SDaniel P. Berrange    """Open an image as a LUKS device"""
1976278ae03SDaniel P. Berrange
1986278ae03SDaniel P. Berrange    (password, slot) = config.first_password()
1996278ae03SDaniel P. Berrange
2006278ae03SDaniel P. Berrange    args = ["luksOpen", config.image_path(), config.device_name()]
2016278ae03SDaniel P. Berrange
2026278ae03SDaniel P. Berrange    cryptsetup(args, password)
2036278ae03SDaniel P. Berrange
2046278ae03SDaniel P. Berrange
2056278ae03SDaniel P. Berrangedef cryptsetup_close(config):
2066278ae03SDaniel P. Berrange    """Close an active LUKS device """
2076278ae03SDaniel P. Berrange
2086278ae03SDaniel P. Berrange    args = ["luksClose", config.device_name()]
2096278ae03SDaniel P. Berrange    cryptsetup(args)
2106278ae03SDaniel P. Berrange
2116278ae03SDaniel P. Berrange
2126278ae03SDaniel P. Berrangedef delete_image(config):
2136278ae03SDaniel P. Berrange    """Delete a disk image"""
2146278ae03SDaniel P. Berrange
2156278ae03SDaniel P. Berrange    try:
2166278ae03SDaniel P. Berrange        os.unlink(config.image_path())
2176278ae03SDaniel P. Berrange        iotests.log("unlink %s" % config.image_path(),
2186278ae03SDaniel P. Berrange                    filters=[iotests.filter_test_dir])
2196278ae03SDaniel P. Berrange    except Exception as e:
2206278ae03SDaniel P. Berrange        pass
2216278ae03SDaniel P. Berrange
2226278ae03SDaniel P. Berrange
2236278ae03SDaniel P. Berrangedef create_image(config, size_mb):
2246278ae03SDaniel P. Berrange    """Create a bare disk image with requested size"""
2256278ae03SDaniel P. Berrange
2266278ae03SDaniel P. Berrange    delete_image(config)
2276278ae03SDaniel P. Berrange    iotests.log("truncate %s --size %dMB" % (config.image_path(), size_mb),
2286278ae03SDaniel P. Berrange                filters=[iotests.filter_test_dir])
2296278ae03SDaniel P. Berrange    with open(config.image_path(), "w") as fn:
2306278ae03SDaniel P. Berrange        fn.truncate(size_mb * 1024 * 1024)
2316278ae03SDaniel P. Berrange
2326278ae03SDaniel P. Berrange
2336278ae03SDaniel P. Berrangedef qemu_img_create(config, size_mb):
2346278ae03SDaniel P. Berrange    """Create and format a disk image with LUKS using qemu-img"""
2356278ae03SDaniel P. Berrange
2366278ae03SDaniel P. Berrange    opts = [
2376278ae03SDaniel P. Berrange        "key-secret=sec0",
238307d9991SDaniel P. Berrange        "iter-time=10",
2396278ae03SDaniel P. Berrange        "cipher-alg=%s-%d" % (config.cipher, config.keylen),
2406278ae03SDaniel P. Berrange        "cipher-mode=%s" % config.mode,
2416278ae03SDaniel P. Berrange        "ivgen-alg=%s" % config.ivgen,
2426278ae03SDaniel P. Berrange        "hash-alg=%s" % config.hash,
2436278ae03SDaniel P. Berrange    ]
2446278ae03SDaniel P. Berrange    if config.ivgen_hash is not None:
2456278ae03SDaniel P. Berrange        opts.append("ivgen-hash-alg=%s" % config.ivgen_hash)
2466278ae03SDaniel P. Berrange
2476278ae03SDaniel P. Berrange    args = ["create", "-f", "luks",
2486278ae03SDaniel P. Berrange            "--object",
2496278ae03SDaniel P. Berrange            ("secret,id=sec0,data=%s,format=base64" %
2506278ae03SDaniel P. Berrange             config.first_password_base64()),
2516278ae03SDaniel P. Berrange            "-o", ",".join(opts),
2526278ae03SDaniel P. Berrange            config.image_path(),
2536278ae03SDaniel P. Berrange            "%dM" % size_mb]
2546278ae03SDaniel P. Berrange
2556278ae03SDaniel P. Berrange    iotests.log("qemu-img " + " ".join(args), filters=[iotests.filter_test_dir])
2566278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_img_pipe(*args), filters=[iotests.filter_test_dir])
2576278ae03SDaniel P. Berrange
2586278ae03SDaniel P. Berrangedef qemu_io_image_args(config, dev=False):
2596278ae03SDaniel P. Berrange    """Get the args for access an image or device with qemu-io"""
2606278ae03SDaniel P. Berrange
2616278ae03SDaniel P. Berrange    if dev:
2626278ae03SDaniel P. Berrange        return [
2636278ae03SDaniel P. Berrange            "--image-opts",
2644e04f3d9SKevin Wolf            "driver=host_device,filename=%s" % config.device_path()]
2656278ae03SDaniel P. Berrange    else:
2666278ae03SDaniel P. Berrange        return [
2676278ae03SDaniel P. Berrange            "--object",
2686278ae03SDaniel P. Berrange            ("secret,id=sec0,data=%s,format=base64" %
2696278ae03SDaniel P. Berrange             config.first_password_base64()),
2706278ae03SDaniel P. Berrange            "--image-opts",
2716278ae03SDaniel P. Berrange            ("driver=luks,key-secret=sec0,file.filename=%s" %
2726278ae03SDaniel P. Berrange             config.image_path())]
2736278ae03SDaniel P. Berrange
2746278ae03SDaniel P. Berrangedef qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
2756278ae03SDaniel P. Berrange    """Write a pattern of data to a LUKS image or device"""
2766278ae03SDaniel P. Berrange
277ae50b71dSDaniel P. Berrange    if dev:
278ae50b71dSDaniel P. Berrange        chown(config)
2796278ae03SDaniel P. Berrange    args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
2806278ae03SDaniel P. Berrange    args.extend(qemu_io_image_args(config, dev))
2816278ae03SDaniel P. Berrange    iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
2826278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
2836278ae03SDaniel P. Berrange                                                 iotests.filter_qemu_io])
2846278ae03SDaniel P. Berrange
2856278ae03SDaniel P. Berrange
2866278ae03SDaniel P. Berrangedef qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
2876278ae03SDaniel P. Berrange    """Read a pattern of data to a LUKS image or device"""
2886278ae03SDaniel P. Berrange
289ae50b71dSDaniel P. Berrange    if dev:
290ae50b71dSDaniel P. Berrange        chown(config)
2916278ae03SDaniel P. Berrange    args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
2926278ae03SDaniel P. Berrange    args.extend(qemu_io_image_args(config, dev))
2936278ae03SDaniel P. Berrange    iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
2946278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
2956278ae03SDaniel P. Berrange                                                 iotests.filter_qemu_io])
2966278ae03SDaniel P. Berrange
2976278ae03SDaniel P. Berrange
2986278ae03SDaniel P. Berrangedef test_once(config, qemu_img=False):
2996278ae03SDaniel P. Berrange    """Run the test with a desired LUKS configuration. Can either
3006278ae03SDaniel P. Berrange       use qemu-img for creating the initial volume, or cryptsetup,
3016278ae03SDaniel P. Berrange       in order to test interoperability in both directions"""
3026278ae03SDaniel P. Berrange
3036278ae03SDaniel P. Berrange    iotests.log("# ================= %s %s =================" % (
3046278ae03SDaniel P. Berrange        "qemu-img" if qemu_img else "dm-crypt", config))
3056278ae03SDaniel P. Berrange
3066278ae03SDaniel P. Berrange    oneKB = 1024
3076278ae03SDaniel P. Berrange    oneMB = oneKB * 1024
3086278ae03SDaniel P. Berrange    oneGB = oneMB * 1024
3096278ae03SDaniel P. Berrange    oneTB = oneGB * 1024
3106278ae03SDaniel P. Berrange
3116278ae03SDaniel P. Berrange    # 4 TB, so that we pass the 32-bit sector number boundary.
3126278ae03SDaniel P. Berrange    # Important for testing correctness of some IV generators
3136278ae03SDaniel P. Berrange    # The files are sparse, so not actually using this much space
3146278ae03SDaniel P. Berrange    image_size = 4 * oneTB
3156278ae03SDaniel P. Berrange    if qemu_img:
3166278ae03SDaniel P. Berrange        iotests.log("# Create image")
3179a3a9a63SMax Reitz        qemu_img_create(config, image_size // oneMB)
3186278ae03SDaniel P. Berrange    else:
3196278ae03SDaniel P. Berrange        iotests.log("# Create image")
3209a3a9a63SMax Reitz        create_image(config, image_size // oneMB)
3216278ae03SDaniel P. Berrange
3226278ae03SDaniel P. Berrange    lowOffsetMB = 100
3239a3a9a63SMax Reitz    highOffsetMB = 3 * oneTB // oneMB
3246278ae03SDaniel P. Berrange
3256278ae03SDaniel P. Berrange    try:
3266278ae03SDaniel P. Berrange        if not qemu_img:
3276278ae03SDaniel P. Berrange            iotests.log("# Format image")
3286278ae03SDaniel P. Berrange            cryptsetup_format(config)
3296278ae03SDaniel P. Berrange
3306278ae03SDaniel P. Berrange            for slot in config.active_slots()[1:]:
3316278ae03SDaniel P. Berrange                iotests.log("# Add password slot %s" % slot)
3326278ae03SDaniel P. Berrange                cryptsetup_add_password(config, slot)
3336278ae03SDaniel P. Berrange
3346278ae03SDaniel P. Berrange        # First we'll open the image using cryptsetup and write a
3356278ae03SDaniel P. Berrange        # known pattern of data that we'll then verify with QEMU
3366278ae03SDaniel P. Berrange
3376278ae03SDaniel P. Berrange        iotests.log("# Open dev")
3386278ae03SDaniel P. Berrange        cryptsetup_open(config)
3396278ae03SDaniel P. Berrange
3406278ae03SDaniel P. Berrange        try:
3416278ae03SDaniel P. Berrange            iotests.log("# Write test pattern 0xa7")
3426278ae03SDaniel P. Berrange            qemu_io_write_pattern(config, 0xa7, lowOffsetMB, 10, dev=True)
3436278ae03SDaniel P. Berrange            iotests.log("# Write test pattern 0x13")
3446278ae03SDaniel P. Berrange            qemu_io_write_pattern(config, 0x13, highOffsetMB, 10, dev=True)
3456278ae03SDaniel P. Berrange        finally:
3466278ae03SDaniel P. Berrange            iotests.log("# Close dev")
3476278ae03SDaniel P. Berrange            cryptsetup_close(config)
3486278ae03SDaniel P. Berrange
3496278ae03SDaniel P. Berrange        # Ok, now we're using QEMU to verify the pattern just
3506278ae03SDaniel P. Berrange        # written via dm-crypt
3516278ae03SDaniel P. Berrange
3526278ae03SDaniel P. Berrange        iotests.log("# Read test pattern 0xa7")
3536278ae03SDaniel P. Berrange        qemu_io_read_pattern(config, 0xa7, lowOffsetMB, 10, dev=False)
3546278ae03SDaniel P. Berrange        iotests.log("# Read test pattern 0x13")
3556278ae03SDaniel P. Berrange        qemu_io_read_pattern(config, 0x13, highOffsetMB, 10, dev=False)
3566278ae03SDaniel P. Berrange
3576278ae03SDaniel P. Berrange
3586278ae03SDaniel P. Berrange        # Write a new pattern to the image, which we'll later
3596278ae03SDaniel P. Berrange        # verify with dm-crypt
3606278ae03SDaniel P. Berrange        iotests.log("# Write test pattern 0x91")
3616278ae03SDaniel P. Berrange        qemu_io_write_pattern(config, 0x91, lowOffsetMB, 10, dev=False)
3626278ae03SDaniel P. Berrange        iotests.log("# Write test pattern 0x5e")
3636278ae03SDaniel P. Berrange        qemu_io_write_pattern(config, 0x5e, highOffsetMB, 10, dev=False)
3646278ae03SDaniel P. Berrange
3656278ae03SDaniel P. Berrange
3666278ae03SDaniel P. Berrange        # Now we're opening the image with dm-crypt once more
3676278ae03SDaniel P. Berrange        # and verifying what QEMU wrote, completing the circle
3686278ae03SDaniel P. Berrange        iotests.log("# Open dev")
3696278ae03SDaniel P. Berrange        cryptsetup_open(config)
3706278ae03SDaniel P. Berrange
3716278ae03SDaniel P. Berrange        try:
3726278ae03SDaniel P. Berrange            iotests.log("# Read test pattern 0x91")
3736278ae03SDaniel P. Berrange            qemu_io_read_pattern(config, 0x91, lowOffsetMB, 10, dev=True)
3746278ae03SDaniel P. Berrange            iotests.log("# Read test pattern 0x5e")
3756278ae03SDaniel P. Berrange            qemu_io_read_pattern(config, 0x5e, highOffsetMB, 10, dev=True)
3766278ae03SDaniel P. Berrange        finally:
3776278ae03SDaniel P. Berrange            iotests.log("# Close dev")
3786278ae03SDaniel P. Berrange            cryptsetup_close(config)
3796278ae03SDaniel P. Berrange    finally:
3806278ae03SDaniel P. Berrange        iotests.log("# Delete image")
3816278ae03SDaniel P. Berrange        delete_image(config)
382f03868bdSEduardo Habkost        print()
3836278ae03SDaniel P. Berrange
3846278ae03SDaniel P. Berrange
3856278ae03SDaniel P. Berrange# Obviously we only work with the luks image format
3866278ae03SDaniel P. Berrangeiotests.verify_image_format(supported_fmts=['luks'])
3876278ae03SDaniel P. Berrangeiotests.verify_platform()
3886278ae03SDaniel P. Berrange
3896278ae03SDaniel P. Berrange# We need sudo in order to run cryptsetup to create
3906278ae03SDaniel P. Berrange# dm-crypt devices. This is safe to use on any
3916278ae03SDaniel P. Berrange# machine, since all dm-crypt devices are backed
3926278ae03SDaniel P. Berrange# by newly created plain files, and have a dm-crypt
3936278ae03SDaniel P. Berrange# name prefix of 'qiotest' to avoid clashing with
3946278ae03SDaniel P. Berrange# user LUKS volumes
3956278ae03SDaniel P. Berrangeverify_passwordless_sudo()
3966278ae03SDaniel P. Berrange
3976278ae03SDaniel P. Berrange
3986278ae03SDaniel P. Berrange# If we look at all permutations of cipher, key size,
3996278ae03SDaniel P. Berrange# mode, ivgen, hash, there are ~1000 possible configs.
4006278ae03SDaniel P. Berrange#
4016278ae03SDaniel P. Berrange# We certainly don't want/need to test every permutation
4026278ae03SDaniel P. Berrange# to get good validation of interoperability between QEMU
4036278ae03SDaniel P. Berrange# and dm-crypt/cryptsetup.
4046278ae03SDaniel P. Berrange#
4056278ae03SDaniel P. Berrange# The configs below are a representative set that aim to
4066278ae03SDaniel P. Berrange# exercise each axis of configurability.
4076278ae03SDaniel P. Berrange#
4086278ae03SDaniel P. Berrangeconfigs = [
4096278ae03SDaniel P. Berrange    # A common LUKS default
4106278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha1",
4116278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha1"),
4126278ae03SDaniel P. Berrange
4136278ae03SDaniel P. Berrange
4146278ae03SDaniel P. Berrange    # LUKS default but diff ciphers
4156278ae03SDaniel P. Berrange    LUKSConfig("twofish-256-xts-plain64-sha1",
4166278ae03SDaniel P. Berrange               "twofish", 256, "xts", "plain64", None, "sha1"),
4176278ae03SDaniel P. Berrange    LUKSConfig("serpent-256-xts-plain64-sha1",
4186278ae03SDaniel P. Berrange               "serpent", 256, "xts", "plain64", None, "sha1"),
4196278ae03SDaniel P. Berrange    # Should really be xts, but kernel doesn't support xts+cast5
4206278ae03SDaniel P. Berrange    # nor does it do essiv+cast5
4216278ae03SDaniel P. Berrange    LUKSConfig("cast5-128-cbc-plain64-sha1",
4226278ae03SDaniel P. Berrange               "cast5", 128, "cbc", "plain64", None, "sha1"),
4236278ae03SDaniel P. Berrange    LUKSConfig("cast6-256-xts-plain64-sha1",
4246278ae03SDaniel P. Berrange               "cast6", 256, "xts", "plain64", None, "sha1"),
4256278ae03SDaniel P. Berrange
4266278ae03SDaniel P. Berrange
4276278ae03SDaniel P. Berrange    # LUKS default but diff modes / ivgens
4286278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain-sha1",
4296278ae03SDaniel P. Berrange               "aes", 256, "cbc", "plain", None, "sha1"),
4306278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain64-sha1",
4316278ae03SDaniel P. Berrange               "aes", 256, "cbc", "plain64", None, "sha1"),
4326278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-essiv-sha256-sha1",
4336278ae03SDaniel P. Berrange               "aes", 256, "cbc", "essiv", "sha256", "sha1"),
4346278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-essiv-sha256-sha1",
4356278ae03SDaniel P. Berrange               "aes", 256, "xts", "essiv", "sha256", "sha1"),
4366278ae03SDaniel P. Berrange
4376278ae03SDaniel P. Berrange
4386278ae03SDaniel P. Berrange    # LUKS default but smaller key sizes
4396278ae03SDaniel P. Berrange    LUKSConfig("aes-128-xts-plain64-sha256-sha1",
4406278ae03SDaniel P. Berrange               "aes", 128, "xts", "plain64", None, "sha1"),
4416278ae03SDaniel P. Berrange    LUKSConfig("aes-192-xts-plain64-sha256-sha1",
4426278ae03SDaniel P. Berrange               "aes", 192, "xts", "plain64", None, "sha1"),
4436278ae03SDaniel P. Berrange
4446278ae03SDaniel P. Berrange    LUKSConfig("twofish-128-xts-plain64-sha1",
4456278ae03SDaniel P. Berrange               "twofish", 128, "xts", "plain64", None, "sha1"),
4466278ae03SDaniel P. Berrange    LUKSConfig("twofish-192-xts-plain64-sha1",
4476278ae03SDaniel P. Berrange               "twofish", 192, "xts", "plain64", None, "sha1"),
4486278ae03SDaniel P. Berrange
4496278ae03SDaniel P. Berrange    LUKSConfig("serpent-128-xts-plain64-sha1",
4506278ae03SDaniel P. Berrange               "serpent", 128, "xts", "plain64", None, "sha1"),
4516278ae03SDaniel P. Berrange    LUKSConfig("serpent-192-xts-plain64-sha1",
4526278ae03SDaniel P. Berrange               "serpent", 192, "xts", "plain64", None, "sha1"),
4536278ae03SDaniel P. Berrange
4546278ae03SDaniel P. Berrange    LUKSConfig("cast6-128-xts-plain64-sha1",
4556278ae03SDaniel P. Berrange               "cast6", 128, "xts", "plain", None, "sha1"),
4566278ae03SDaniel P. Berrange    LUKSConfig("cast6-192-xts-plain64-sha1",
4576278ae03SDaniel P. Berrange               "cast6", 192, "xts", "plain64", None, "sha1"),
4586278ae03SDaniel P. Berrange
4596278ae03SDaniel P. Berrange
4606278ae03SDaniel P. Berrange    # LUKS default but diff hash
461a488e71eSDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha224",
462a488e71eSDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha224"),
4636278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha256",
4646278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha256"),
465a488e71eSDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha384",
466a488e71eSDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha384"),
4676278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha512",
4686278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha512"),
4696278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-ripemd160",
4706278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "ripemd160"),
4716278ae03SDaniel P. Berrange
4726278ae03SDaniel P. Berrange    # Password in slot 3
4736278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain-sha1-pwslot3",
4746278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain", None, "sha1",
4756278ae03SDaniel P. Berrange               passwords={
4766278ae03SDaniel P. Berrange                   "3": "slot3",
4776278ae03SDaniel P. Berrange               }),
4786278ae03SDaniel P. Berrange
4796278ae03SDaniel P. Berrange    # Passwords in every slot
4806278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain-sha1-pwallslots",
4816278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain", None, "sha1",
4826278ae03SDaniel P. Berrange               passwords={
4836278ae03SDaniel P. Berrange                   "0": "slot1",
4846278ae03SDaniel P. Berrange                   "1": "slot1",
4856278ae03SDaniel P. Berrange                   "2": "slot2",
4866278ae03SDaniel P. Berrange                   "3": "slot3",
4876278ae03SDaniel P. Berrange                   "4": "slot4",
4886278ae03SDaniel P. Berrange                   "5": "slot5",
4896278ae03SDaniel P. Berrange                   "6": "slot6",
4906278ae03SDaniel P. Berrange                   "7": "slot7",
4916278ae03SDaniel P. Berrange               }),
4928b7cdba3SDaniel P. Berrange
4938b7cdba3SDaniel P. Berrange    # Check handling of default hash alg (sha256) with essiv
4948b7cdba3SDaniel P. Berrange    LUKSConfig("aes-256-cbc-essiv-auto-sha1",
4958b7cdba3SDaniel P. Berrange               "aes", 256, "cbc", "essiv", None, "sha1"),
4968b7cdba3SDaniel P. Berrange
4978b7cdba3SDaniel P. Berrange    # Check that a useless hash provided for 'plain64' iv gen
4988b7cdba3SDaniel P. Berrange    # is ignored and no error raised
4998b7cdba3SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain64-sha256-sha1",
5008b7cdba3SDaniel P. Berrange               "aes", 256, "cbc", "plain64", "sha256", "sha1"),
5018b7cdba3SDaniel P. Berrange
5026278ae03SDaniel P. Berrange]
5036278ae03SDaniel P. Berrange
5046278ae03SDaniel P. Berrangeblacklist = [
5056278ae03SDaniel P. Berrange    # We don't have a cast-6 cipher impl for QEMU yet
5066278ae03SDaniel P. Berrange    "cast6-256-xts-plain64-sha1",
5076278ae03SDaniel P. Berrange    "cast6-128-xts-plain64-sha1",
5086278ae03SDaniel P. Berrange    "cast6-192-xts-plain64-sha1",
5096278ae03SDaniel P. Berrange
5106278ae03SDaniel P. Berrange    # GCrypt doesn't support Twofish with 192 bit key
5116278ae03SDaniel P. Berrange    "twofish-192-xts-plain64-sha1",
5126278ae03SDaniel P. Berrange]
5136278ae03SDaniel P. Berrange
5146278ae03SDaniel P. Berrangewhitelist = []
5156278ae03SDaniel P. Berrangeif "LUKS_CONFIG" in os.environ:
5166278ae03SDaniel P. Berrange    whitelist = os.environ["LUKS_CONFIG"].split(",")
5176278ae03SDaniel P. Berrange
5186278ae03SDaniel P. Berrangefor config in configs:
5196278ae03SDaniel P. Berrange    if config.name in blacklist:
5206278ae03SDaniel P. Berrange        iotests.log("Skipping %s in blacklist" % config.name)
5216278ae03SDaniel P. Berrange        continue
5226278ae03SDaniel P. Berrange
5236278ae03SDaniel P. Berrange    if len(whitelist) > 0 and config.name not in whitelist:
5246278ae03SDaniel P. Berrange        iotests.log("Skipping %s not in whitelist" % config.name)
5256278ae03SDaniel P. Berrange        continue
5266278ae03SDaniel P. Berrange
5276278ae03SDaniel P. Berrange    test_once(config, qemu_img=False)
5286278ae03SDaniel P. Berrange
5296278ae03SDaniel P. Berrange    # XXX we should support setting passwords in a non-0
5306278ae03SDaniel P. Berrange    # key slot with 'qemu-img create' in future
5316278ae03SDaniel P. Berrange    (pw, slot) = config.first_password()
5326278ae03SDaniel P. Berrange    if slot == "0":
5336278ae03SDaniel P. Berrange        test_once(config, qemu_img=True)
534