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