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