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