xref: /openbmc/qemu/tests/qemu-iotests/149 (revision 6278ae035fbd4bbab6a43cd53e4bf3bb71debc71)
1*6278ae03SDaniel P. Berrange#!/usr/bin/python
2*6278ae03SDaniel P. Berrange#
3*6278ae03SDaniel P. Berrange# Copyright (C) 2016 Red Hat, Inc.
4*6278ae03SDaniel P. Berrange#
5*6278ae03SDaniel P. Berrange# This program is free software; you can redistribute it and/or modify
6*6278ae03SDaniel P. Berrange# it under the terms of the GNU General Public License as published by
7*6278ae03SDaniel P. Berrange# the Free Software Foundation; either version 2 of the License, or
8*6278ae03SDaniel P. Berrange# (at your option) any later version.
9*6278ae03SDaniel P. Berrange#
10*6278ae03SDaniel P. Berrange# This program is distributed in the hope that it will be useful,
11*6278ae03SDaniel P. Berrange# but WITHOUT ANY WARRANTY; without even the implied warranty of
12*6278ae03SDaniel P. Berrange# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*6278ae03SDaniel P. Berrange# GNU General Public License for more details.
14*6278ae03SDaniel P. Berrange#
15*6278ae03SDaniel P. Berrange# You should have received a copy of the GNU General Public License
16*6278ae03SDaniel P. Berrange# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17*6278ae03SDaniel P. Berrange#
18*6278ae03SDaniel P. Berrange# Creator/Owner: Daniel P. Berrange <berrange@redhat.com>
19*6278ae03SDaniel P. Berrange#
20*6278ae03SDaniel P. Berrange# Exercise the QEMU 'luks' block driver to validate interoperability
21*6278ae03SDaniel P. Berrange# with the Linux dm-crypt + cryptsetup implementation
22*6278ae03SDaniel P. Berrange
23*6278ae03SDaniel P. Berrangeimport subprocess
24*6278ae03SDaniel P. Berrangeimport os
25*6278ae03SDaniel P. Berrangeimport os.path
26*6278ae03SDaniel P. Berrange
27*6278ae03SDaniel P. Berrangeimport base64
28*6278ae03SDaniel P. Berrange
29*6278ae03SDaniel P. Berrangeimport iotests
30*6278ae03SDaniel P. Berrange
31*6278ae03SDaniel P. Berrange
32*6278ae03SDaniel P. Berrangeclass LUKSConfig(object):
33*6278ae03SDaniel P. Berrange    """Represent configuration parameters for a single LUKS
34*6278ae03SDaniel P. Berrange       setup to be tested"""
35*6278ae03SDaniel P. Berrange
36*6278ae03SDaniel P. Berrange    def __init__(self, name, cipher, keylen, mode, ivgen,
37*6278ae03SDaniel P. Berrange                 ivgen_hash, hash, password=None, passwords=None):
38*6278ae03SDaniel P. Berrange
39*6278ae03SDaniel P. Berrange        self.name = name
40*6278ae03SDaniel P. Berrange        self.cipher = cipher
41*6278ae03SDaniel P. Berrange        self.keylen = keylen
42*6278ae03SDaniel P. Berrange        self.mode = mode
43*6278ae03SDaniel P. Berrange        self.ivgen = ivgen
44*6278ae03SDaniel P. Berrange        self.ivgen_hash = ivgen_hash
45*6278ae03SDaniel P. Berrange        self.hash = hash
46*6278ae03SDaniel P. Berrange
47*6278ae03SDaniel P. Berrange        if passwords is not None:
48*6278ae03SDaniel P. Berrange            self.passwords = passwords
49*6278ae03SDaniel P. Berrange        else:
50*6278ae03SDaniel P. Berrange            self.passwords = {}
51*6278ae03SDaniel P. Berrange
52*6278ae03SDaniel P. Berrange            if password is None:
53*6278ae03SDaniel P. Berrange                self.passwords["0"] = "123456"
54*6278ae03SDaniel P. Berrange            else:
55*6278ae03SDaniel P. Berrange                self.passwords["0"] = password
56*6278ae03SDaniel P. Berrange
57*6278ae03SDaniel P. Berrange    def __repr__(self):
58*6278ae03SDaniel P. Berrange        return self.name
59*6278ae03SDaniel P. Berrange
60*6278ae03SDaniel P. Berrange    def image_name(self):
61*6278ae03SDaniel P. Berrange        return "luks-%s.img" % self.name
62*6278ae03SDaniel P. Berrange
63*6278ae03SDaniel P. Berrange    def image_path(self):
64*6278ae03SDaniel P. Berrange        return os.path.join(iotests.test_dir, self.image_name())
65*6278ae03SDaniel P. Berrange
66*6278ae03SDaniel P. Berrange    def device_name(self):
67*6278ae03SDaniel P. Berrange        return "qiotest-145-%s" % self.name
68*6278ae03SDaniel P. Berrange
69*6278ae03SDaniel P. Berrange    def device_path(self):
70*6278ae03SDaniel P. Berrange        return "/dev/mapper/" + self.device_name()
71*6278ae03SDaniel P. Berrange
72*6278ae03SDaniel P. Berrange    def first_password(self):
73*6278ae03SDaniel P. Berrange        for i in range(8):
74*6278ae03SDaniel P. Berrange            slot = str(i)
75*6278ae03SDaniel P. Berrange            if slot in self.passwords:
76*6278ae03SDaniel P. Berrange                return (self.passwords[slot], slot)
77*6278ae03SDaniel P. Berrange        raise Exception("No password found")
78*6278ae03SDaniel P. Berrange
79*6278ae03SDaniel P. Berrange    def first_password_base64(self):
80*6278ae03SDaniel P. Berrange        (pw, slot) = self.first_password()
81*6278ae03SDaniel P. Berrange        return base64.b64encode(pw)
82*6278ae03SDaniel P. Berrange
83*6278ae03SDaniel P. Berrange    def active_slots(self):
84*6278ae03SDaniel P. Berrange        slots = []
85*6278ae03SDaniel P. Berrange        for i in range(8):
86*6278ae03SDaniel P. Berrange            slot = str(i)
87*6278ae03SDaniel P. Berrange            if slot in self.passwords:
88*6278ae03SDaniel P. Berrange                slots.append(slot)
89*6278ae03SDaniel P. Berrange        return slots
90*6278ae03SDaniel P. Berrange
91*6278ae03SDaniel P. Berrangedef verify_passwordless_sudo():
92*6278ae03SDaniel P. Berrange    """Check whether sudo is configured to allow
93*6278ae03SDaniel P. Berrange       password-less access to commands"""
94*6278ae03SDaniel P. Berrange
95*6278ae03SDaniel P. Berrange    args = ["sudo", "-n", "/bin/true"]
96*6278ae03SDaniel P. Berrange
97*6278ae03SDaniel P. Berrange    proc = subprocess.Popen(args,
98*6278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
99*6278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
100*6278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
101*6278ae03SDaniel P. Berrange
102*6278ae03SDaniel P. Berrange    msg = proc.communicate()[0]
103*6278ae03SDaniel P. Berrange
104*6278ae03SDaniel P. Berrange    if proc.returncode != 0:
105*6278ae03SDaniel P. Berrange        iotests.notrun('requires password-less sudo access: %s' % msg)
106*6278ae03SDaniel P. Berrange
107*6278ae03SDaniel P. Berrange
108*6278ae03SDaniel P. Berrangedef cryptsetup(args, password=None):
109*6278ae03SDaniel P. Berrange    """Run the cryptsetup command in batch mode"""
110*6278ae03SDaniel P. Berrange
111*6278ae03SDaniel P. Berrange    fullargs = ["sudo", "cryptsetup", "-q", "-v"]
112*6278ae03SDaniel P. Berrange    fullargs.extend(args)
113*6278ae03SDaniel P. Berrange
114*6278ae03SDaniel P. Berrange    iotests.log(" ".join(fullargs), filters=[iotests.filter_test_dir])
115*6278ae03SDaniel P. Berrange    proc = subprocess.Popen(fullargs,
116*6278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
117*6278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
118*6278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
119*6278ae03SDaniel P. Berrange
120*6278ae03SDaniel P. Berrange    msg = proc.communicate(password)[0]
121*6278ae03SDaniel P. Berrange
122*6278ae03SDaniel P. Berrange    if proc.returncode != 0:
123*6278ae03SDaniel P. Berrange        raise Exception(msg)
124*6278ae03SDaniel P. Berrange
125*6278ae03SDaniel P. Berrange
126*6278ae03SDaniel P. Berrangedef cryptsetup_add_password(config, slot):
127*6278ae03SDaniel P. Berrange    """Add another password to a LUKS key slot"""
128*6278ae03SDaniel P. Berrange
129*6278ae03SDaniel P. Berrange    (password, mainslot) = config.first_password()
130*6278ae03SDaniel P. Berrange
131*6278ae03SDaniel P. Berrange    pwfile = os.path.join(iotests.test_dir, "passwd.txt")
132*6278ae03SDaniel P. Berrange    with open(pwfile, "w") as fh:
133*6278ae03SDaniel P. Berrange        fh.write(config.passwords[slot])
134*6278ae03SDaniel P. Berrange
135*6278ae03SDaniel P. Berrange    try:
136*6278ae03SDaniel P. Berrange        args = ["luksAddKey", config.image_path(),
137*6278ae03SDaniel P. Berrange                "--key-slot", slot,
138*6278ae03SDaniel P. Berrange                "--key-file", "-",
139*6278ae03SDaniel P. Berrange                pwfile]
140*6278ae03SDaniel P. Berrange
141*6278ae03SDaniel P. Berrange        cryptsetup(args, password)
142*6278ae03SDaniel P. Berrange    finally:
143*6278ae03SDaniel P. Berrange        os.unlink(pwfile)
144*6278ae03SDaniel P. Berrange
145*6278ae03SDaniel P. Berrange
146*6278ae03SDaniel P. Berrangedef cryptsetup_format(config):
147*6278ae03SDaniel P. Berrange    """Format a new LUKS volume with cryptsetup, adding the
148*6278ae03SDaniel P. Berrange    first key slot only"""
149*6278ae03SDaniel P. Berrange
150*6278ae03SDaniel P. Berrange    (password, slot) = config.first_password()
151*6278ae03SDaniel P. Berrange
152*6278ae03SDaniel P. Berrange    args = ["luksFormat"]
153*6278ae03SDaniel P. Berrange    cipher = config.cipher + "-" + config.mode + "-" + config.ivgen
154*6278ae03SDaniel P. Berrange    if config.ivgen_hash is not None:
155*6278ae03SDaniel P. Berrange        cipher = cipher + ":" + config.ivgen_hash
156*6278ae03SDaniel P. Berrange    args.extend(["--cipher", cipher])
157*6278ae03SDaniel P. Berrange    if config.mode == "xts":
158*6278ae03SDaniel P. Berrange        args.extend(["--key-size", str(config.keylen * 2)])
159*6278ae03SDaniel P. Berrange    else:
160*6278ae03SDaniel P. Berrange        args.extend(["--key-size", str(config.keylen)])
161*6278ae03SDaniel P. Berrange    if config.hash is not None:
162*6278ae03SDaniel P. Berrange        args.extend(["--hash", config.hash])
163*6278ae03SDaniel P. Berrange    args.extend(["--key-slot", slot])
164*6278ae03SDaniel P. Berrange    args.extend(["--key-file", "-"])
165*6278ae03SDaniel P. Berrange    args.append(config.image_path())
166*6278ae03SDaniel P. Berrange
167*6278ae03SDaniel P. Berrange    cryptsetup(args, password)
168*6278ae03SDaniel P. Berrange
169*6278ae03SDaniel P. Berrange
170*6278ae03SDaniel P. Berrangedef chown(config):
171*6278ae03SDaniel P. Berrange    """Set the ownership of a open LUKS device to this user"""
172*6278ae03SDaniel P. Berrange
173*6278ae03SDaniel P. Berrange    path = config.device_path()
174*6278ae03SDaniel P. Berrange
175*6278ae03SDaniel P. Berrange    args = ["sudo", "chown", "%d:%d" % (os.getuid(), os.getgid()), path]
176*6278ae03SDaniel P. Berrange    iotests.log(" ".join(args), filters=[iotests.filter_chown])
177*6278ae03SDaniel P. Berrange    proc = subprocess.Popen(args,
178*6278ae03SDaniel P. Berrange                            stdin=subprocess.PIPE,
179*6278ae03SDaniel P. Berrange                            stdout=subprocess.PIPE,
180*6278ae03SDaniel P. Berrange                            stderr=subprocess.STDOUT)
181*6278ae03SDaniel P. Berrange
182*6278ae03SDaniel P. Berrange    msg = proc.communicate()[0]
183*6278ae03SDaniel P. Berrange
184*6278ae03SDaniel P. Berrange    if proc.returncode != 0:
185*6278ae03SDaniel P. Berrange        raise Exception("Cannot change owner on %s" % path)
186*6278ae03SDaniel P. Berrange
187*6278ae03SDaniel P. Berrange
188*6278ae03SDaniel P. Berrangedef cryptsetup_open(config):
189*6278ae03SDaniel P. Berrange    """Open an image as a LUKS device"""
190*6278ae03SDaniel P. Berrange
191*6278ae03SDaniel P. Berrange    (password, slot) = config.first_password()
192*6278ae03SDaniel P. Berrange
193*6278ae03SDaniel P. Berrange    args = ["luksOpen", config.image_path(), config.device_name()]
194*6278ae03SDaniel P. Berrange
195*6278ae03SDaniel P. Berrange    cryptsetup(args, password)
196*6278ae03SDaniel P. Berrange
197*6278ae03SDaniel P. Berrange
198*6278ae03SDaniel P. Berrangedef cryptsetup_close(config):
199*6278ae03SDaniel P. Berrange    """Close an active LUKS device """
200*6278ae03SDaniel P. Berrange
201*6278ae03SDaniel P. Berrange    args = ["luksClose", config.device_name()]
202*6278ae03SDaniel P. Berrange    cryptsetup(args)
203*6278ae03SDaniel P. Berrange
204*6278ae03SDaniel P. Berrange
205*6278ae03SDaniel P. Berrangedef delete_image(config):
206*6278ae03SDaniel P. Berrange    """Delete a disk image"""
207*6278ae03SDaniel P. Berrange
208*6278ae03SDaniel P. Berrange    try:
209*6278ae03SDaniel P. Berrange        os.unlink(config.image_path())
210*6278ae03SDaniel P. Berrange        iotests.log("unlink %s" % config.image_path(),
211*6278ae03SDaniel P. Berrange                    filters=[iotests.filter_test_dir])
212*6278ae03SDaniel P. Berrange    except Exception as e:
213*6278ae03SDaniel P. Berrange        pass
214*6278ae03SDaniel P. Berrange
215*6278ae03SDaniel P. Berrange
216*6278ae03SDaniel P. Berrangedef create_image(config, size_mb):
217*6278ae03SDaniel P. Berrange    """Create a bare disk image with requested size"""
218*6278ae03SDaniel P. Berrange
219*6278ae03SDaniel P. Berrange    delete_image(config)
220*6278ae03SDaniel P. Berrange    iotests.log("truncate %s --size %dMB" % (config.image_path(), size_mb),
221*6278ae03SDaniel P. Berrange                filters=[iotests.filter_test_dir])
222*6278ae03SDaniel P. Berrange    with open(config.image_path(), "w") as fn:
223*6278ae03SDaniel P. Berrange        fn.truncate(size_mb * 1024 * 1024)
224*6278ae03SDaniel P. Berrange
225*6278ae03SDaniel P. Berrange
226*6278ae03SDaniel P. Berrangedef qemu_img_create(config, size_mb):
227*6278ae03SDaniel P. Berrange    """Create and format a disk image with LUKS using qemu-img"""
228*6278ae03SDaniel P. Berrange
229*6278ae03SDaniel P. Berrange    opts = [
230*6278ae03SDaniel P. Berrange        "key-secret=sec0",
231*6278ae03SDaniel P. Berrange        "cipher-alg=%s-%d" % (config.cipher, config.keylen),
232*6278ae03SDaniel P. Berrange        "cipher-mode=%s" % config.mode,
233*6278ae03SDaniel P. Berrange        "ivgen-alg=%s" % config.ivgen,
234*6278ae03SDaniel P. Berrange        "hash-alg=%s" % config.hash,
235*6278ae03SDaniel P. Berrange    ]
236*6278ae03SDaniel P. Berrange    if config.ivgen_hash is not None:
237*6278ae03SDaniel P. Berrange        opts.append("ivgen-hash-alg=%s" % config.ivgen_hash)
238*6278ae03SDaniel P. Berrange
239*6278ae03SDaniel P. Berrange    args = ["create", "-f", "luks",
240*6278ae03SDaniel P. Berrange            "--object",
241*6278ae03SDaniel P. Berrange            ("secret,id=sec0,data=%s,format=base64" %
242*6278ae03SDaniel P. Berrange             config.first_password_base64()),
243*6278ae03SDaniel P. Berrange            "-o", ",".join(opts),
244*6278ae03SDaniel P. Berrange            config.image_path(),
245*6278ae03SDaniel P. Berrange            "%dM" % size_mb]
246*6278ae03SDaniel P. Berrange
247*6278ae03SDaniel P. Berrange    iotests.log("qemu-img " + " ".join(args), filters=[iotests.filter_test_dir])
248*6278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_img_pipe(*args), filters=[iotests.filter_test_dir])
249*6278ae03SDaniel P. Berrange
250*6278ae03SDaniel P. Berrangedef qemu_io_image_args(config, dev=False):
251*6278ae03SDaniel P. Berrange    """Get the args for access an image or device with qemu-io"""
252*6278ae03SDaniel P. Berrange
253*6278ae03SDaniel P. Berrange    if dev:
254*6278ae03SDaniel P. Berrange        return [
255*6278ae03SDaniel P. Berrange            "--image-opts",
256*6278ae03SDaniel P. Berrange            "driver=file,filename=%s" % config.device_path()]
257*6278ae03SDaniel P. Berrange    else:
258*6278ae03SDaniel P. Berrange        return [
259*6278ae03SDaniel P. Berrange            "--object",
260*6278ae03SDaniel P. Berrange            ("secret,id=sec0,data=%s,format=base64" %
261*6278ae03SDaniel P. Berrange             config.first_password_base64()),
262*6278ae03SDaniel P. Berrange            "--image-opts",
263*6278ae03SDaniel P. Berrange            ("driver=luks,key-secret=sec0,file.filename=%s" %
264*6278ae03SDaniel P. Berrange             config.image_path())]
265*6278ae03SDaniel P. Berrange
266*6278ae03SDaniel P. Berrangedef qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
267*6278ae03SDaniel P. Berrange    """Write a pattern of data to a LUKS image or device"""
268*6278ae03SDaniel P. Berrange
269*6278ae03SDaniel P. Berrange    args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
270*6278ae03SDaniel P. Berrange    args.extend(qemu_io_image_args(config, dev))
271*6278ae03SDaniel P. Berrange    iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
272*6278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
273*6278ae03SDaniel P. Berrange                                                 iotests.filter_qemu_io])
274*6278ae03SDaniel P. Berrange
275*6278ae03SDaniel P. Berrange
276*6278ae03SDaniel P. Berrangedef qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
277*6278ae03SDaniel P. Berrange    """Read a pattern of data to a LUKS image or device"""
278*6278ae03SDaniel P. Berrange
279*6278ae03SDaniel P. Berrange    args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
280*6278ae03SDaniel P. Berrange    args.extend(qemu_io_image_args(config, dev))
281*6278ae03SDaniel P. Berrange    iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
282*6278ae03SDaniel P. Berrange    iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
283*6278ae03SDaniel P. Berrange                                                 iotests.filter_qemu_io])
284*6278ae03SDaniel P. Berrange
285*6278ae03SDaniel P. Berrange
286*6278ae03SDaniel P. Berrangedef test_once(config, qemu_img=False):
287*6278ae03SDaniel P. Berrange    """Run the test with a desired LUKS configuration. Can either
288*6278ae03SDaniel P. Berrange       use qemu-img for creating the initial volume, or cryptsetup,
289*6278ae03SDaniel P. Berrange       in order to test interoperability in both directions"""
290*6278ae03SDaniel P. Berrange
291*6278ae03SDaniel P. Berrange    iotests.log("# ================= %s %s =================" % (
292*6278ae03SDaniel P. Berrange        "qemu-img" if qemu_img else "dm-crypt", config))
293*6278ae03SDaniel P. Berrange
294*6278ae03SDaniel P. Berrange    oneKB = 1024
295*6278ae03SDaniel P. Berrange    oneMB = oneKB * 1024
296*6278ae03SDaniel P. Berrange    oneGB = oneMB * 1024
297*6278ae03SDaniel P. Berrange    oneTB = oneGB * 1024
298*6278ae03SDaniel P. Berrange
299*6278ae03SDaniel P. Berrange    # 4 TB, so that we pass the 32-bit sector number boundary.
300*6278ae03SDaniel P. Berrange    # Important for testing correctness of some IV generators
301*6278ae03SDaniel P. Berrange    # The files are sparse, so not actually using this much space
302*6278ae03SDaniel P. Berrange    image_size = 4 * oneTB
303*6278ae03SDaniel P. Berrange    if qemu_img:
304*6278ae03SDaniel P. Berrange        iotests.log("# Create image")
305*6278ae03SDaniel P. Berrange        qemu_img_create(config, image_size / oneMB)
306*6278ae03SDaniel P. Berrange    else:
307*6278ae03SDaniel P. Berrange        iotests.log("# Create image")
308*6278ae03SDaniel P. Berrange        create_image(config, image_size / oneMB)
309*6278ae03SDaniel P. Berrange
310*6278ae03SDaniel P. Berrange    lowOffsetMB = 100
311*6278ae03SDaniel P. Berrange    highOffsetMB = 3 * oneTB / oneMB
312*6278ae03SDaniel P. Berrange
313*6278ae03SDaniel P. Berrange    try:
314*6278ae03SDaniel P. Berrange        if not qemu_img:
315*6278ae03SDaniel P. Berrange            iotests.log("# Format image")
316*6278ae03SDaniel P. Berrange            cryptsetup_format(config)
317*6278ae03SDaniel P. Berrange
318*6278ae03SDaniel P. Berrange            for slot in config.active_slots()[1:]:
319*6278ae03SDaniel P. Berrange                iotests.log("# Add password slot %s" % slot)
320*6278ae03SDaniel P. Berrange                cryptsetup_add_password(config, slot)
321*6278ae03SDaniel P. Berrange
322*6278ae03SDaniel P. Berrange        # First we'll open the image using cryptsetup and write a
323*6278ae03SDaniel P. Berrange        # known pattern of data that we'll then verify with QEMU
324*6278ae03SDaniel P. Berrange
325*6278ae03SDaniel P. Berrange        iotests.log("# Open dev")
326*6278ae03SDaniel P. Berrange        cryptsetup_open(config)
327*6278ae03SDaniel P. Berrange
328*6278ae03SDaniel P. Berrange        try:
329*6278ae03SDaniel P. Berrange            iotests.log("# Set dev owner")
330*6278ae03SDaniel P. Berrange            chown(config)
331*6278ae03SDaniel P. Berrange
332*6278ae03SDaniel P. Berrange            iotests.log("# Write test pattern 0xa7")
333*6278ae03SDaniel P. Berrange            qemu_io_write_pattern(config, 0xa7, lowOffsetMB, 10, dev=True)
334*6278ae03SDaniel P. Berrange            iotests.log("# Write test pattern 0x13")
335*6278ae03SDaniel P. Berrange            qemu_io_write_pattern(config, 0x13, highOffsetMB, 10, dev=True)
336*6278ae03SDaniel P. Berrange        finally:
337*6278ae03SDaniel P. Berrange            iotests.log("# Close dev")
338*6278ae03SDaniel P. Berrange            cryptsetup_close(config)
339*6278ae03SDaniel P. Berrange
340*6278ae03SDaniel P. Berrange        # Ok, now we're using QEMU to verify the pattern just
341*6278ae03SDaniel P. Berrange        # written via dm-crypt
342*6278ae03SDaniel P. Berrange
343*6278ae03SDaniel P. Berrange        iotests.log("# Read test pattern 0xa7")
344*6278ae03SDaniel P. Berrange        qemu_io_read_pattern(config, 0xa7, lowOffsetMB, 10, dev=False)
345*6278ae03SDaniel P. Berrange        iotests.log("# Read test pattern 0x13")
346*6278ae03SDaniel P. Berrange        qemu_io_read_pattern(config, 0x13, highOffsetMB, 10, dev=False)
347*6278ae03SDaniel P. Berrange
348*6278ae03SDaniel P. Berrange
349*6278ae03SDaniel P. Berrange        # Write a new pattern to the image, which we'll later
350*6278ae03SDaniel P. Berrange        # verify with dm-crypt
351*6278ae03SDaniel P. Berrange        iotests.log("# Write test pattern 0x91")
352*6278ae03SDaniel P. Berrange        qemu_io_write_pattern(config, 0x91, lowOffsetMB, 10, dev=False)
353*6278ae03SDaniel P. Berrange        iotests.log("# Write test pattern 0x5e")
354*6278ae03SDaniel P. Berrange        qemu_io_write_pattern(config, 0x5e, highOffsetMB, 10, dev=False)
355*6278ae03SDaniel P. Berrange
356*6278ae03SDaniel P. Berrange
357*6278ae03SDaniel P. Berrange        # Now we're opening the image with dm-crypt once more
358*6278ae03SDaniel P. Berrange        # and verifying what QEMU wrote, completing the circle
359*6278ae03SDaniel P. Berrange        iotests.log("# Open dev")
360*6278ae03SDaniel P. Berrange        cryptsetup_open(config)
361*6278ae03SDaniel P. Berrange
362*6278ae03SDaniel P. Berrange        try:
363*6278ae03SDaniel P. Berrange            iotests.log("# Set dev owner")
364*6278ae03SDaniel P. Berrange            chown(config)
365*6278ae03SDaniel P. Berrange
366*6278ae03SDaniel P. Berrange            iotests.log("# Read test pattern 0x91")
367*6278ae03SDaniel P. Berrange            qemu_io_read_pattern(config, 0x91, lowOffsetMB, 10, dev=True)
368*6278ae03SDaniel P. Berrange            iotests.log("# Read test pattern 0x5e")
369*6278ae03SDaniel P. Berrange            qemu_io_read_pattern(config, 0x5e, highOffsetMB, 10, dev=True)
370*6278ae03SDaniel P. Berrange        finally:
371*6278ae03SDaniel P. Berrange            iotests.log("# Close dev")
372*6278ae03SDaniel P. Berrange            cryptsetup_close(config)
373*6278ae03SDaniel P. Berrange    finally:
374*6278ae03SDaniel P. Berrange        iotests.log("# Delete image")
375*6278ae03SDaniel P. Berrange        delete_image(config)
376*6278ae03SDaniel P. Berrange        print
377*6278ae03SDaniel P. Berrange
378*6278ae03SDaniel P. Berrange
379*6278ae03SDaniel P. Berrange# Obviously we only work with the luks image format
380*6278ae03SDaniel P. Berrangeiotests.verify_image_format(supported_fmts=['luks'])
381*6278ae03SDaniel P. Berrangeiotests.verify_platform()
382*6278ae03SDaniel P. Berrange
383*6278ae03SDaniel P. Berrange# We need sudo in order to run cryptsetup to create
384*6278ae03SDaniel P. Berrange# dm-crypt devices. This is safe to use on any
385*6278ae03SDaniel P. Berrange# machine, since all dm-crypt devices are backed
386*6278ae03SDaniel P. Berrange# by newly created plain files, and have a dm-crypt
387*6278ae03SDaniel P. Berrange# name prefix of 'qiotest' to avoid clashing with
388*6278ae03SDaniel P. Berrange# user LUKS volumes
389*6278ae03SDaniel P. Berrangeverify_passwordless_sudo()
390*6278ae03SDaniel P. Berrange
391*6278ae03SDaniel P. Berrange
392*6278ae03SDaniel P. Berrange# If we look at all permutations of cipher, key size,
393*6278ae03SDaniel P. Berrange# mode, ivgen, hash, there are ~1000 possible configs.
394*6278ae03SDaniel P. Berrange#
395*6278ae03SDaniel P. Berrange# We certainly don't want/need to test every permutation
396*6278ae03SDaniel P. Berrange# to get good validation of interoperability between QEMU
397*6278ae03SDaniel P. Berrange# and dm-crypt/cryptsetup.
398*6278ae03SDaniel P. Berrange#
399*6278ae03SDaniel P. Berrange# The configs below are a representative set that aim to
400*6278ae03SDaniel P. Berrange# exercise each axis of configurability.
401*6278ae03SDaniel P. Berrange#
402*6278ae03SDaniel P. Berrangeconfigs = [
403*6278ae03SDaniel P. Berrange    # A common LUKS default
404*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha1",
405*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha1"),
406*6278ae03SDaniel P. Berrange
407*6278ae03SDaniel P. Berrange
408*6278ae03SDaniel P. Berrange    # LUKS default but diff ciphers
409*6278ae03SDaniel P. Berrange    LUKSConfig("twofish-256-xts-plain64-sha1",
410*6278ae03SDaniel P. Berrange               "twofish", 256, "xts", "plain64", None, "sha1"),
411*6278ae03SDaniel P. Berrange    LUKSConfig("serpent-256-xts-plain64-sha1",
412*6278ae03SDaniel P. Berrange               "serpent", 256, "xts", "plain64", None, "sha1"),
413*6278ae03SDaniel P. Berrange    # Should really be xts, but kernel doesn't support xts+cast5
414*6278ae03SDaniel P. Berrange    # nor does it do essiv+cast5
415*6278ae03SDaniel P. Berrange    LUKSConfig("cast5-128-cbc-plain64-sha1",
416*6278ae03SDaniel P. Berrange               "cast5", 128, "cbc", "plain64", None, "sha1"),
417*6278ae03SDaniel P. Berrange    LUKSConfig("cast6-256-xts-plain64-sha1",
418*6278ae03SDaniel P. Berrange               "cast6", 256, "xts", "plain64", None, "sha1"),
419*6278ae03SDaniel P. Berrange
420*6278ae03SDaniel P. Berrange
421*6278ae03SDaniel P. Berrange    # LUKS default but diff modes / ivgens
422*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain-sha1",
423*6278ae03SDaniel P. Berrange               "aes", 256, "cbc", "plain", None, "sha1"),
424*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-plain64-sha1",
425*6278ae03SDaniel P. Berrange               "aes", 256, "cbc", "plain64", None, "sha1"),
426*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-cbc-essiv-sha256-sha1",
427*6278ae03SDaniel P. Berrange               "aes", 256, "cbc", "essiv", "sha256", "sha1"),
428*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-essiv-sha256-sha1",
429*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "essiv", "sha256", "sha1"),
430*6278ae03SDaniel P. Berrange
431*6278ae03SDaniel P. Berrange
432*6278ae03SDaniel P. Berrange    # LUKS default but smaller key sizes
433*6278ae03SDaniel P. Berrange    LUKSConfig("aes-128-xts-plain64-sha256-sha1",
434*6278ae03SDaniel P. Berrange               "aes", 128, "xts", "plain64", None, "sha1"),
435*6278ae03SDaniel P. Berrange    LUKSConfig("aes-192-xts-plain64-sha256-sha1",
436*6278ae03SDaniel P. Berrange               "aes", 192, "xts", "plain64", None, "sha1"),
437*6278ae03SDaniel P. Berrange
438*6278ae03SDaniel P. Berrange    LUKSConfig("twofish-128-xts-plain64-sha1",
439*6278ae03SDaniel P. Berrange               "twofish", 128, "xts", "plain64", None, "sha1"),
440*6278ae03SDaniel P. Berrange    LUKSConfig("twofish-192-xts-plain64-sha1",
441*6278ae03SDaniel P. Berrange               "twofish", 192, "xts", "plain64", None, "sha1"),
442*6278ae03SDaniel P. Berrange
443*6278ae03SDaniel P. Berrange    LUKSConfig("serpent-128-xts-plain64-sha1",
444*6278ae03SDaniel P. Berrange               "serpent", 128, "xts", "plain64", None, "sha1"),
445*6278ae03SDaniel P. Berrange    LUKSConfig("serpent-192-xts-plain64-sha1",
446*6278ae03SDaniel P. Berrange               "serpent", 192, "xts", "plain64", None, "sha1"),
447*6278ae03SDaniel P. Berrange
448*6278ae03SDaniel P. Berrange    LUKSConfig("cast6-128-xts-plain64-sha1",
449*6278ae03SDaniel P. Berrange               "cast6", 128, "xts", "plain", None, "sha1"),
450*6278ae03SDaniel P. Berrange    LUKSConfig("cast6-192-xts-plain64-sha1",
451*6278ae03SDaniel P. Berrange               "cast6", 192, "xts", "plain64", None, "sha1"),
452*6278ae03SDaniel P. Berrange
453*6278ae03SDaniel P. Berrange
454*6278ae03SDaniel P. Berrange    # LUKS default but diff hash
455*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha256",
456*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha256"),
457*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-sha512",
458*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "sha512"),
459*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain64-ripemd160",
460*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain64", None, "ripemd160"),
461*6278ae03SDaniel P. Berrange
462*6278ae03SDaniel P. Berrange    # Password in slot 3
463*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain-sha1-pwslot3",
464*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain", None, "sha1",
465*6278ae03SDaniel P. Berrange               passwords={
466*6278ae03SDaniel P. Berrange                   "3": "slot3",
467*6278ae03SDaniel P. Berrange               }),
468*6278ae03SDaniel P. Berrange
469*6278ae03SDaniel P. Berrange    # Passwords in every slot
470*6278ae03SDaniel P. Berrange    LUKSConfig("aes-256-xts-plain-sha1-pwallslots",
471*6278ae03SDaniel P. Berrange               "aes", 256, "xts", "plain", None, "sha1",
472*6278ae03SDaniel P. Berrange               passwords={
473*6278ae03SDaniel P. Berrange                   "0": "slot1",
474*6278ae03SDaniel P. Berrange                   "1": "slot1",
475*6278ae03SDaniel P. Berrange                   "2": "slot2",
476*6278ae03SDaniel P. Berrange                   "3": "slot3",
477*6278ae03SDaniel P. Berrange                   "4": "slot4",
478*6278ae03SDaniel P. Berrange                   "5": "slot5",
479*6278ae03SDaniel P. Berrange                   "6": "slot6",
480*6278ae03SDaniel P. Berrange                   "7": "slot7",
481*6278ae03SDaniel P. Berrange               }),
482*6278ae03SDaniel P. Berrange]
483*6278ae03SDaniel P. Berrange
484*6278ae03SDaniel P. Berrangeblacklist = [
485*6278ae03SDaniel P. Berrange    # We don't have a cast-6 cipher impl for QEMU yet
486*6278ae03SDaniel P. Berrange    "cast6-256-xts-plain64-sha1",
487*6278ae03SDaniel P. Berrange    "cast6-128-xts-plain64-sha1",
488*6278ae03SDaniel P. Berrange    "cast6-192-xts-plain64-sha1",
489*6278ae03SDaniel P. Berrange
490*6278ae03SDaniel P. Berrange    # GCrypt doesn't support Twofish with 192 bit key
491*6278ae03SDaniel P. Berrange    "twofish-192-xts-plain64-sha1",
492*6278ae03SDaniel P. Berrange
493*6278ae03SDaniel P. Berrange    # We don't have sha512 hash wired up yet
494*6278ae03SDaniel P. Berrange    "aes-256-xts-plain64-sha512",
495*6278ae03SDaniel P. Berrange
496*6278ae03SDaniel P. Berrange    # We don't have ripemd160 hash wired up yet
497*6278ae03SDaniel P. Berrange    "aes-256-xts-plain64-ripemd160",
498*6278ae03SDaniel P. Berrange]
499*6278ae03SDaniel P. Berrange
500*6278ae03SDaniel P. Berrangewhitelist = []
501*6278ae03SDaniel P. Berrangeif "LUKS_CONFIG" in os.environ:
502*6278ae03SDaniel P. Berrange    whitelist = os.environ["LUKS_CONFIG"].split(",")
503*6278ae03SDaniel P. Berrange
504*6278ae03SDaniel P. Berrangefor config in configs:
505*6278ae03SDaniel P. Berrange    if config.name in blacklist:
506*6278ae03SDaniel P. Berrange        iotests.log("Skipping %s in blacklist" % config.name)
507*6278ae03SDaniel P. Berrange        continue
508*6278ae03SDaniel P. Berrange
509*6278ae03SDaniel P. Berrange    if len(whitelist) > 0 and config.name not in whitelist:
510*6278ae03SDaniel P. Berrange        iotests.log("Skipping %s not in whitelist" % config.name)
511*6278ae03SDaniel P. Berrange        continue
512*6278ae03SDaniel P. Berrange
513*6278ae03SDaniel P. Berrange    test_once(config, qemu_img=False)
514*6278ae03SDaniel P. Berrange
515*6278ae03SDaniel P. Berrange    # XXX we should support setting passwords in a non-0
516*6278ae03SDaniel P. Berrange    # key slot with 'qemu-img create' in future
517*6278ae03SDaniel P. Berrange    (pw, slot) = config.first_password()
518*6278ae03SDaniel P. Berrange    if slot == "0":
519*6278ae03SDaniel P. Berrange        test_once(config, qemu_img=True)
520