13e308f20SDaniel P. Berrange /* 23e308f20SDaniel P. Berrange * QEMU Crypto block device encryption LUKS format 33e308f20SDaniel P. Berrange * 43e308f20SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 53e308f20SDaniel P. Berrange * 63e308f20SDaniel P. Berrange * This library is free software; you can redistribute it and/or 73e308f20SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 83e308f20SDaniel P. Berrange * License as published by the Free Software Foundation; either 9b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 103e308f20SDaniel P. Berrange * 113e308f20SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 123e308f20SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 133e308f20SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143e308f20SDaniel P. Berrange * Lesser General Public License for more details. 153e308f20SDaniel P. Berrange * 163e308f20SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 173e308f20SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 183e308f20SDaniel P. Berrange * 193e308f20SDaniel P. Berrange */ 203e308f20SDaniel P. Berrange 213e308f20SDaniel P. Berrange #include "qemu/osdep.h" 22da34e65cSMarkus Armbruster #include "qapi/error.h" 2358369e22SPaolo Bonzini #include "qemu/bswap.h" 243e308f20SDaniel P. Berrange 25986bc8deSMichael S. Tsirkin #include "block-luks.h" 263e308f20SDaniel P. Berrange 273e308f20SDaniel P. Berrange #include "crypto/hash.h" 283e308f20SDaniel P. Berrange #include "crypto/afsplit.h" 293e308f20SDaniel P. Berrange #include "crypto/pbkdf.h" 303e308f20SDaniel P. Berrange #include "crypto/secret.h" 313e308f20SDaniel P. Berrange #include "crypto/random.h" 322ef950f9SFam Zheng #include "qemu/uuid.h" 333e308f20SDaniel P. Berrange 343e308f20SDaniel P. Berrange #include "qemu/coroutine.h" 35557d2bdcSMaxim Levitsky #include "qemu/bitmap.h" 363e308f20SDaniel P. Berrange 373e308f20SDaniel P. Berrange /* 383e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is 393e308f20SDaniel P. Berrange * 403e308f20SDaniel P. Berrange * docs/on-disk-format.pdf 413e308f20SDaniel P. Berrange * 423e308f20SDaniel P. Berrange * in 'cryptsetup' package source code 433e308f20SDaniel P. Berrange * 443e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated 453e308f20SDaniel P. Berrange * Oct 16, 2011. 463e308f20SDaniel P. Berrange */ 473e308f20SDaniel P. Berrange 483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS; 493e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSHeader QCryptoBlockLUKSHeader; 503e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot; 513e308f20SDaniel P. Berrange 523e308f20SDaniel P. Berrange 533e308f20SDaniel P. Berrange /* The following constants are all defined by the LUKS spec */ 543e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_VERSION 1 553e308f20SDaniel P. Berrange 563e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MAGIC_LEN 6 573e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN 32 583e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN 32 593e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN 32 603e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_DIGEST_LEN 20 613e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SALT_LEN 32 623e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_UUID_LEN 40 633e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS 8 643e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_STRIPES 4000 653e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS 1000 663e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS 1000 673e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET 4096 683e308f20SDaniel P. Berrange 693e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED 0x0000DEAD 703e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3 713e308f20SDaniel P. Berrange 723e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL 733e308f20SDaniel P. Berrange 74557d2bdcSMaxim Levitsky #define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS 2000 75557d2bdcSMaxim Levitsky #define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40 76557d2bdcSMaxim Levitsky 773e308f20SDaniel P. Berrange static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = { 783e308f20SDaniel P. Berrange 'L', 'U', 'K', 'S', 0xBA, 0xBE 793e308f20SDaniel P. Berrange }; 803e308f20SDaniel P. Berrange 813e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap; 823e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap { 833e308f20SDaniel P. Berrange const char *name; 843e308f20SDaniel P. Berrange int id; 853e308f20SDaniel P. Berrange }; 863e308f20SDaniel P. Berrange 873e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap; 883e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap { 893e308f20SDaniel P. Berrange uint32_t key_bytes; 903e308f20SDaniel P. Berrange int id; 913e308f20SDaniel P. Berrange }; 923e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap; 933e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap { 943e308f20SDaniel P. Berrange const char *name; 953e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes; 963e308f20SDaniel P. Berrange }; 973e308f20SDaniel P. Berrange 983e308f20SDaniel P. Berrange 993e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1003e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = { 1013e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 }, 1023e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 }, 1033e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 }, 1043e308f20SDaniel P. Berrange { 0, 0 }, 1053e308f20SDaniel P. Berrange }; 1063e308f20SDaniel P. Berrange 1073e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1083e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = { 1093e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 }, 1103e308f20SDaniel P. Berrange { 0, 0 }, 1113e308f20SDaniel P. Berrange }; 1123e308f20SDaniel P. Berrange 1133e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1143e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = { 1153e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 }, 1163e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 }, 1173e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 }, 1183e308f20SDaniel P. Berrange { 0, 0 }, 1193e308f20SDaniel P. Berrange }; 1203e308f20SDaniel P. Berrange 1213e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1223e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = { 1233e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 }, 1243e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 }, 1253e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 }, 1263e308f20SDaniel P. Berrange { 0, 0 }, 1273e308f20SDaniel P. Berrange }; 1283e308f20SDaniel P. Berrange 1293e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap 1303e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = { 1313e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes }, 1323e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, 1333e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, 1343e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, 1353e308f20SDaniel P. Berrange }; 1363e308f20SDaniel P. Berrange 1373e308f20SDaniel P. Berrange 1383e308f20SDaniel P. Berrange /* 1393e308f20SDaniel P. Berrange * This struct is written to disk in big-endian format, 1403e308f20SDaniel P. Berrange * but operated upon in native-endian format. 1413e308f20SDaniel P. Berrange */ 1423e308f20SDaniel P. Berrange struct QCryptoBlockLUKSKeySlot { 1433e308f20SDaniel P. Berrange /* state of keyslot, enabled/disable */ 1443e308f20SDaniel P. Berrange uint32_t active; 1453e308f20SDaniel P. Berrange /* iterations for PBKDF2 */ 1463e308f20SDaniel P. Berrange uint32_t iterations; 1473e308f20SDaniel P. Berrange /* salt for PBKDF2 */ 1483e308f20SDaniel P. Berrange uint8_t salt[QCRYPTO_BLOCK_LUKS_SALT_LEN]; 1493e308f20SDaniel P. Berrange /* start sector of key material */ 150f0d3c362SMaxim Levitsky uint32_t key_offset_sector; 1513e308f20SDaniel P. Berrange /* number of anti-forensic stripes */ 1523e308f20SDaniel P. Berrange uint32_t stripes; 1535993e3beSGreg Kurz }; 1543e308f20SDaniel P. Berrange 1553e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); 1563e308f20SDaniel P. Berrange 1573e308f20SDaniel P. Berrange 1583e308f20SDaniel P. Berrange /* 1593e308f20SDaniel P. Berrange * This struct is written to disk in big-endian format, 1603e308f20SDaniel P. Berrange * but operated upon in native-endian format. 1613e308f20SDaniel P. Berrange */ 1623e308f20SDaniel P. Berrange struct QCryptoBlockLUKSHeader { 1633e308f20SDaniel P. Berrange /* 'L', 'U', 'K', 'S', '0xBA', '0xBE' */ 1643e308f20SDaniel P. Berrange char magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN]; 1653e308f20SDaniel P. Berrange 1663e308f20SDaniel P. Berrange /* LUKS version, currently 1 */ 1673e308f20SDaniel P. Berrange uint16_t version; 1683e308f20SDaniel P. Berrange 1693e308f20SDaniel P. Berrange /* cipher name specification (aes, etc) */ 1703e308f20SDaniel P. Berrange char cipher_name[QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN]; 1713e308f20SDaniel P. Berrange 1723e308f20SDaniel P. Berrange /* cipher mode specification (cbc-plain, xts-essiv:sha256, etc) */ 1733e308f20SDaniel P. Berrange char cipher_mode[QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN]; 1743e308f20SDaniel P. Berrange 1753e308f20SDaniel P. Berrange /* hash specification (sha256, etc) */ 1763e308f20SDaniel P. Berrange char hash_spec[QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN]; 1773e308f20SDaniel P. Berrange 1783e308f20SDaniel P. Berrange /* start offset of the volume data (in 512 byte sectors) */ 179f0d3c362SMaxim Levitsky uint32_t payload_offset_sector; 1803e308f20SDaniel P. Berrange 1813e308f20SDaniel P. Berrange /* Number of key bytes */ 182f0d3c362SMaxim Levitsky uint32_t master_key_len; 1833e308f20SDaniel P. Berrange 1843e308f20SDaniel P. Berrange /* master key checksum after PBKDF2 */ 1853e308f20SDaniel P. Berrange uint8_t master_key_digest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 1863e308f20SDaniel P. Berrange 1873e308f20SDaniel P. Berrange /* salt for master key PBKDF2 */ 1883e308f20SDaniel P. Berrange uint8_t master_key_salt[QCRYPTO_BLOCK_LUKS_SALT_LEN]; 1893e308f20SDaniel P. Berrange 1903e308f20SDaniel P. Berrange /* iterations for master key PBKDF2 */ 1913e308f20SDaniel P. Berrange uint32_t master_key_iterations; 1923e308f20SDaniel P. Berrange 1933e308f20SDaniel P. Berrange /* UUID of the partition in standard ASCII representation */ 1943e308f20SDaniel P. Berrange uint8_t uuid[QCRYPTO_BLOCK_LUKS_UUID_LEN]; 1953e308f20SDaniel P. Berrange 1963e308f20SDaniel P. Berrange /* key slots */ 1973e308f20SDaniel P. Berrange QCryptoBlockLUKSKeySlot key_slots[QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS]; 1985993e3beSGreg Kurz }; 1993e308f20SDaniel P. Berrange 2003e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592); 2013e308f20SDaniel P. Berrange 2023e308f20SDaniel P. Berrange 2033e308f20SDaniel P. Berrange struct QCryptoBlockLUKS { 2043e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header; 20540c85028SDaniel P. Berrange 2069d80e59dSMaxim Levitsky /* Main encryption algorithm used for encryption*/ 20740c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 2089d80e59dSMaxim Levitsky 2099d80e59dSMaxim Levitsky /* Mode of encryption for the selected encryption algorithm */ 21040c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 2119d80e59dSMaxim Levitsky 2129d80e59dSMaxim Levitsky /* Initialization vector generation algorithm */ 21340c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 2149d80e59dSMaxim Levitsky 2159d80e59dSMaxim Levitsky /* Hash algorithm used for IV generation*/ 21640c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 2179d80e59dSMaxim Levitsky 2189d80e59dSMaxim Levitsky /* 2199d80e59dSMaxim Levitsky * Encryption algorithm used for IV generation. 2209d80e59dSMaxim Levitsky * Usually the same as main encryption algorithm 2219d80e59dSMaxim Levitsky */ 2229d80e59dSMaxim Levitsky QCryptoCipherAlgorithm ivgen_cipher_alg; 2239d80e59dSMaxim Levitsky 2249d80e59dSMaxim Levitsky /* Hash algorithm used in pbkdf2 function */ 22540c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 226557d2bdcSMaxim Levitsky 227557d2bdcSMaxim Levitsky /* Name of the secret that was used to open the image */ 228557d2bdcSMaxim Levitsky char *secret; 2293e308f20SDaniel P. Berrange }; 2303e308f20SDaniel P. Berrange 2313e308f20SDaniel P. Berrange 2323e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name, 2333e308f20SDaniel P. Berrange QCryptoCipherMode mode, 2343e308f20SDaniel P. Berrange uint32_t key_bytes, 2353e308f20SDaniel P. Berrange Error **errp) 2363e308f20SDaniel P. Berrange { 2373e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2383e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2393e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2403e308f20SDaniel P. Berrange size_t i, j; 2413e308f20SDaniel P. Berrange 2423e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) { 2433e308f20SDaniel P. Berrange key_bytes /= 2; 2443e308f20SDaniel P. Berrange } 2453e308f20SDaniel P. Berrange 2463e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2473e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) { 2483e308f20SDaniel P. Berrange continue; 2493e308f20SDaniel P. Berrange } 2503e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2513e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) { 2523e308f20SDaniel P. Berrange return map[i].sizes[j].id; 2533e308f20SDaniel P. Berrange } 2543e308f20SDaniel P. Berrange } 2553e308f20SDaniel P. Berrange } 2563e308f20SDaniel P. Berrange 2573e308f20SDaniel P. Berrange error_setg(errp, "Algorithm %s with key size %d bytes not supported", 2583e308f20SDaniel P. Berrange name, key_bytes); 2593e308f20SDaniel P. Berrange return 0; 2603e308f20SDaniel P. Berrange } 2613e308f20SDaniel P. Berrange 2623e308f20SDaniel P. Berrange static const char * 2633e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg, 2643e308f20SDaniel P. Berrange Error **errp) 2653e308f20SDaniel P. Berrange { 2663e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2673e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2683e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2693e308f20SDaniel P. Berrange size_t i, j; 2703e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2713e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2723e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) { 2733e308f20SDaniel P. Berrange return map[i].name; 2743e308f20SDaniel P. Berrange } 2753e308f20SDaniel P. Berrange } 2763e308f20SDaniel P. Berrange } 2773e308f20SDaniel P. Berrange 2783e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported", 279977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(alg)); 2803e308f20SDaniel P. Berrange return NULL; 2813e308f20SDaniel P. Berrange } 2823e308f20SDaniel P. Berrange 2833e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can 2843e308f20SDaniel P. Berrange * make that function emit a more friendly error message */ 2853e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name, 286f7abe0ecSMarc-André Lureau const QEnumLookup *map, 2873e308f20SDaniel P. Berrange const char *type, 2883e308f20SDaniel P. Berrange Error **errp) 2893e308f20SDaniel P. Berrange { 2909ae33079SMarkus Armbruster int ret = qapi_enum_parse(map, name, -1, NULL); 2913e308f20SDaniel P. Berrange 2929ae33079SMarkus Armbruster if (ret < 0) { 2933e308f20SDaniel P. Berrange error_setg(errp, "%s %s not supported", type, name); 2943e308f20SDaniel P. Berrange return 0; 2953e308f20SDaniel P. Berrange } 2969ae33079SMarkus Armbruster return ret; 2979ae33079SMarkus Armbruster } 2983e308f20SDaniel P. Berrange 2993e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \ 3003e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 301f7abe0ecSMarc-André Lureau &QCryptoCipherMode_lookup, \ 3023e308f20SDaniel P. Berrange "Cipher mode", \ 3033e308f20SDaniel P. Berrange errp) 3043e308f20SDaniel P. Berrange 3053e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \ 3063e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 307f7abe0ecSMarc-André Lureau &QCryptoHashAlgorithm_lookup, \ 3083e308f20SDaniel P. Berrange "Hash algorithm", \ 3093e308f20SDaniel P. Berrange errp) 3103e308f20SDaniel P. Berrange 3113e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \ 3123e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 313f7abe0ecSMarc-André Lureau &QCryptoIVGenAlgorithm_lookup, \ 3143e308f20SDaniel P. Berrange "IV generator", \ 3153e308f20SDaniel P. Berrange errp) 3163e308f20SDaniel P. Berrange 3173e308f20SDaniel P. Berrange 3183e308f20SDaniel P. Berrange static bool 3193e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf, 3203e308f20SDaniel P. Berrange size_t buf_size) 3213e308f20SDaniel P. Berrange { 3223e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf; 3233e308f20SDaniel P. Berrange 3243e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) && 3253e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic, 3263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 && 3273e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) { 3283e308f20SDaniel P. Berrange return true; 3293e308f20SDaniel P. Berrange } else { 3303e308f20SDaniel P. Berrange return false; 3313e308f20SDaniel P. Berrange } 3323e308f20SDaniel P. Berrange } 3333e308f20SDaniel P. Berrange 3343e308f20SDaniel P. Berrange 3353e308f20SDaniel P. Berrange /** 3363e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV. 3373e308f20SDaniel P. Berrange * 3383e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV 3393e308f20SDaniel P. Berrange * may be different from the cipher length used for the block 3403e308f20SDaniel P. Berrange * encryption, becauses dm-crypt uses the hash digest length 3413e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher 3423e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as 3433e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest 3443e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined 3453e308f20SDaniel P. Berrange */ 3463e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm 3473e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher, 3483e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 3493e308f20SDaniel P. Berrange Error **errp) 3503e308f20SDaniel P. Berrange { 3513e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 3523e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher); 3533e308f20SDaniel P. Berrange if (digestlen == keylen) { 3543e308f20SDaniel P. Berrange return cipher; 3553e308f20SDaniel P. Berrange } 3563e308f20SDaniel P. Berrange 3573e308f20SDaniel P. Berrange switch (cipher) { 3583e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128: 3593e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192: 3603e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256: 3613e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3623e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) { 3633e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128; 3643e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3653e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) { 3663e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192; 3673e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3683e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) { 3693e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256; 3703e308f20SDaniel P. Berrange } else { 3713e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available", 3723e308f20SDaniel P. Berrange digestlen); 3733e308f20SDaniel P. Berrange return 0; 3743e308f20SDaniel P. Berrange } 3753e308f20SDaniel P. Berrange break; 3763e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128: 3773e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192: 3783e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256: 3793e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3803e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) { 3813e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128; 3823e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3833e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) { 3843e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192; 3853e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3863e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) { 3873e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256; 3883e308f20SDaniel P. Berrange } else { 3893e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available", 3903e308f20SDaniel P. Berrange digestlen); 3913e308f20SDaniel P. Berrange return 0; 3923e308f20SDaniel P. Berrange } 3933e308f20SDaniel P. Berrange break; 3943e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128: 3953e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192: 3963e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256: 3973e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3983e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) { 3993e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128; 4003e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 4013e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) { 4023e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192; 4033e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 4043e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) { 4053e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256; 4063e308f20SDaniel P. Berrange } else { 4073e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available", 4083e308f20SDaniel P. Berrange digestlen); 4093e308f20SDaniel P. Berrange return 0; 4103e308f20SDaniel P. Berrange } 4113e308f20SDaniel P. Berrange break; 4123e308f20SDaniel P. Berrange default: 4133e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv", 414977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(cipher)); 4153e308f20SDaniel P. Berrange return 0; 4163e308f20SDaniel P. Berrange } 4173e308f20SDaniel P. Berrange } 4183e308f20SDaniel P. Berrange 4193e308f20SDaniel P. Berrange /* 420bd56a55aSMaxim Levitsky * Returns number of sectors needed to store the key material 421bd56a55aSMaxim Levitsky * given number of anti forensic stripes 422bd56a55aSMaxim Levitsky */ 423bd56a55aSMaxim Levitsky static int 424bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks, 425bd56a55aSMaxim Levitsky unsigned int header_sectors, 426bd56a55aSMaxim Levitsky unsigned int stripes) 427bd56a55aSMaxim Levitsky { 428bd56a55aSMaxim Levitsky /* 429bd56a55aSMaxim Levitsky * This calculation doesn't match that shown in the spec, 430bd56a55aSMaxim Levitsky * but instead follows the cryptsetup implementation. 431bd56a55aSMaxim Levitsky */ 432bd56a55aSMaxim Levitsky 433bd56a55aSMaxim Levitsky size_t splitkeylen = luks->header.master_key_len * stripes; 434bd56a55aSMaxim Levitsky 435bd56a55aSMaxim Levitsky /* First align the key material size to block size*/ 436bd56a55aSMaxim Levitsky size_t splitkeylen_sectors = 437bd56a55aSMaxim Levitsky DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE); 438bd56a55aSMaxim Levitsky 439bd56a55aSMaxim Levitsky /* Then also align the key material size to the size of the header */ 440bd56a55aSMaxim Levitsky return ROUND_UP(splitkeylen_sectors, header_sectors); 441bd56a55aSMaxim Levitsky } 442bd56a55aSMaxim Levitsky 443bd56a55aSMaxim Levitsky /* 444dde2c5afSMaxim Levitsky * Stores the main LUKS header, taking care of endianess 445dde2c5afSMaxim Levitsky */ 446dde2c5afSMaxim Levitsky static int 447dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block, 448dde2c5afSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 449dde2c5afSMaxim Levitsky void *opaque, 450dde2c5afSMaxim Levitsky Error **errp) 451dde2c5afSMaxim Levitsky { 452dde2c5afSMaxim Levitsky const QCryptoBlockLUKS *luks = block->opaque; 453dde2c5afSMaxim Levitsky Error *local_err = NULL; 454dde2c5afSMaxim Levitsky size_t i; 455dde2c5afSMaxim Levitsky g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL; 456dde2c5afSMaxim Levitsky 457dde2c5afSMaxim Levitsky /* Create a copy of the header */ 458dde2c5afSMaxim Levitsky hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1); 459dde2c5afSMaxim Levitsky memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader)); 460dde2c5afSMaxim Levitsky 461dde2c5afSMaxim Levitsky /* 462dde2c5afSMaxim Levitsky * Everything on disk uses Big Endian (tm), so flip header fields 463dde2c5afSMaxim Levitsky * before writing them 464dde2c5afSMaxim Levitsky */ 465dde2c5afSMaxim Levitsky cpu_to_be16s(&hdr_copy->version); 466dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->payload_offset_sector); 467dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->master_key_len); 468dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->master_key_iterations); 469dde2c5afSMaxim Levitsky 470dde2c5afSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 471dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].active); 472dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].iterations); 473dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].key_offset_sector); 474dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].stripes); 475dde2c5afSMaxim Levitsky } 476dde2c5afSMaxim Levitsky 477dde2c5afSMaxim Levitsky /* Write out the partition header and key slot headers */ 478dde2c5afSMaxim Levitsky writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy), 479dde2c5afSMaxim Levitsky opaque, &local_err); 480dde2c5afSMaxim Levitsky 481dde2c5afSMaxim Levitsky if (local_err) { 482dde2c5afSMaxim Levitsky error_propagate(errp, local_err); 483dde2c5afSMaxim Levitsky return -1; 484dde2c5afSMaxim Levitsky } 485dde2c5afSMaxim Levitsky return 0; 486dde2c5afSMaxim Levitsky } 487dde2c5afSMaxim Levitsky 488dde2c5afSMaxim Levitsky /* 489dde2c5afSMaxim Levitsky * Loads the main LUKS header,and byteswaps it to native endianess 490dde2c5afSMaxim Levitsky * And run basic sanity checks on it 491dde2c5afSMaxim Levitsky */ 492dde2c5afSMaxim Levitsky static int 493dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block, 494dde2c5afSMaxim Levitsky QCryptoBlockReadFunc readfunc, 495dde2c5afSMaxim Levitsky void *opaque, 496dde2c5afSMaxim Levitsky Error **errp) 497dde2c5afSMaxim Levitsky { 498757dda54SAlberto Faria int rv; 499dde2c5afSMaxim Levitsky size_t i; 500dde2c5afSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 501dde2c5afSMaxim Levitsky 502dde2c5afSMaxim Levitsky /* 503dde2c5afSMaxim Levitsky * Read the entire LUKS header, minus the key material from 504dde2c5afSMaxim Levitsky * the underlying device 505dde2c5afSMaxim Levitsky */ 506dde2c5afSMaxim Levitsky rv = readfunc(block, 0, 507dde2c5afSMaxim Levitsky (uint8_t *)&luks->header, 508dde2c5afSMaxim Levitsky sizeof(luks->header), 509dde2c5afSMaxim Levitsky opaque, 510dde2c5afSMaxim Levitsky errp); 511dde2c5afSMaxim Levitsky if (rv < 0) { 512dde2c5afSMaxim Levitsky return rv; 513dde2c5afSMaxim Levitsky } 514dde2c5afSMaxim Levitsky 515dde2c5afSMaxim Levitsky /* 516dde2c5afSMaxim Levitsky * The header is always stored in big-endian format, so 517dde2c5afSMaxim Levitsky * convert everything to native 518dde2c5afSMaxim Levitsky */ 519dde2c5afSMaxim Levitsky be16_to_cpus(&luks->header.version); 520dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.payload_offset_sector); 521dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.master_key_len); 522dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.master_key_iterations); 523dde2c5afSMaxim Levitsky 524dde2c5afSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 525dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].active); 526dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].iterations); 527dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].key_offset_sector); 528dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].stripes); 529dde2c5afSMaxim Levitsky } 530dde2c5afSMaxim Levitsky 531dde2c5afSMaxim Levitsky return 0; 532dde2c5afSMaxim Levitsky } 533dde2c5afSMaxim Levitsky 534dde2c5afSMaxim Levitsky /* 5359fa9c1c2SMaxim Levitsky * Does basic sanity checks on the LUKS header 5369fa9c1c2SMaxim Levitsky */ 5379fa9c1c2SMaxim Levitsky static int 5389fa9c1c2SMaxim Levitsky qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp) 5399fa9c1c2SMaxim Levitsky { 540befdba9eSMaxim Levitsky size_t i, j; 541befdba9eSMaxim Levitsky 542befdba9eSMaxim Levitsky unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 543befdba9eSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 544befdba9eSMaxim Levitsky 5459fa9c1c2SMaxim Levitsky if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 5469fa9c1c2SMaxim Levitsky QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 5479fa9c1c2SMaxim Levitsky error_setg(errp, "Volume is not in LUKS format"); 5489fa9c1c2SMaxim Levitsky return -1; 5499fa9c1c2SMaxim Levitsky } 5509fa9c1c2SMaxim Levitsky 5519fa9c1c2SMaxim Levitsky if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 5529fa9c1c2SMaxim Levitsky error_setg(errp, "LUKS version %" PRIu32 " is not supported", 5539fa9c1c2SMaxim Levitsky luks->header.version); 5549fa9c1c2SMaxim Levitsky return -1; 5559fa9c1c2SMaxim Levitsky } 556befdba9eSMaxim Levitsky 557c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_name, '\0', 558c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_name))) { 559c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher name is not NUL terminated"); 560c1d8634cSDaniel P. Berrangé return -1; 561c1d8634cSDaniel P. Berrangé } 562c1d8634cSDaniel P. Berrangé 563c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_mode, '\0', 564c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_mode))) { 565c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher mode is not NUL terminated"); 566c1d8634cSDaniel P. Berrangé return -1; 567c1d8634cSDaniel P. Berrangé } 568c1d8634cSDaniel P. Berrangé 569c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.hash_spec, '\0', 570c1d8634cSDaniel P. Berrangé sizeof(luks->header.hash_spec))) { 571c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header hash spec is not NUL terminated"); 572c1d8634cSDaniel P. Berrangé return -1; 573c1d8634cSDaniel P. Berrangé } 574c1d8634cSDaniel P. Berrangé 575d233fbc3SDaniel P. Berrangé if (luks->header.payload_offset_sector < 576d233fbc3SDaniel P. Berrangé DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 577d233fbc3SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 578d233fbc3SDaniel P. Berrangé error_setg(errp, "LUKS payload is overlapping with the header"); 579d233fbc3SDaniel P. Berrangé return -1; 580d233fbc3SDaniel P. Berrangé } 581d233fbc3SDaniel P. Berrangé 582befdba9eSMaxim Levitsky /* Check all keyslots for corruption */ 583befdba9eSMaxim Levitsky for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) { 584befdba9eSMaxim Levitsky 585befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i]; 586befdba9eSMaxim Levitsky unsigned int start1 = slot1->key_offset_sector; 587befdba9eSMaxim Levitsky unsigned int len1 = 588befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 589befdba9eSMaxim Levitsky header_sectors, 590befdba9eSMaxim Levitsky slot1->stripes); 591befdba9eSMaxim Levitsky 592f1195961SDaniel P. Berrangé if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) { 593f1195961SDaniel P. Berrangé error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)", 594f1195961SDaniel P. Berrangé i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES); 595befdba9eSMaxim Levitsky return -1; 596befdba9eSMaxim Levitsky } 597befdba9eSMaxim Levitsky 598befdba9eSMaxim Levitsky if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED && 599befdba9eSMaxim Levitsky slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 600befdba9eSMaxim Levitsky error_setg(errp, 601befdba9eSMaxim Levitsky "Keyslot %zu state (active/disable) is corrupted", i); 602befdba9eSMaxim Levitsky return -1; 603befdba9eSMaxim Levitsky } 604befdba9eSMaxim Levitsky 605c5f69628SDaniel P. Berrangé if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 60693569c37SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 60793569c37SDaniel P. Berrangé error_setg(errp, 60893569c37SDaniel P. Berrangé "Keyslot %zu is overlapping with the LUKS header", 60993569c37SDaniel P. Berrangé i); 61093569c37SDaniel P. Berrangé return -1; 61193569c37SDaniel P. Berrangé } 61293569c37SDaniel P. Berrangé 613befdba9eSMaxim Levitsky if (start1 + len1 > luks->header.payload_offset_sector) { 614befdba9eSMaxim Levitsky error_setg(errp, 615befdba9eSMaxim Levitsky "Keyslot %zu is overlapping with the encrypted payload", 616befdba9eSMaxim Levitsky i); 617befdba9eSMaxim Levitsky return -1; 618befdba9eSMaxim Levitsky } 619befdba9eSMaxim Levitsky 620befdba9eSMaxim Levitsky for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) { 621befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j]; 622befdba9eSMaxim Levitsky unsigned int start2 = slot2->key_offset_sector; 623befdba9eSMaxim Levitsky unsigned int len2 = 624befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 625befdba9eSMaxim Levitsky header_sectors, 626befdba9eSMaxim Levitsky slot2->stripes); 627befdba9eSMaxim Levitsky 628befdba9eSMaxim Levitsky if (start1 + len1 > start2 && start2 + len2 > start1) { 629befdba9eSMaxim Levitsky error_setg(errp, 630befdba9eSMaxim Levitsky "Keyslots %zu and %zu are overlapping in the header", 631befdba9eSMaxim Levitsky i, j); 632befdba9eSMaxim Levitsky return -1; 633befdba9eSMaxim Levitsky } 634befdba9eSMaxim Levitsky } 635befdba9eSMaxim Levitsky 636befdba9eSMaxim Levitsky } 6379fa9c1c2SMaxim Levitsky return 0; 6389fa9c1c2SMaxim Levitsky } 6399fa9c1c2SMaxim Levitsky 6409fa9c1c2SMaxim Levitsky /* 6419fa9c1c2SMaxim Levitsky * Parses the crypto parameters that are stored in the LUKS header 6429fa9c1c2SMaxim Levitsky */ 6439fa9c1c2SMaxim Levitsky 6449fa9c1c2SMaxim Levitsky static int 6459fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp) 6469fa9c1c2SMaxim Levitsky { 6479fa9c1c2SMaxim Levitsky g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode); 6489fa9c1c2SMaxim Levitsky char *ivgen_name, *ivhash_name; 6499fa9c1c2SMaxim Levitsky Error *local_err = NULL; 6509fa9c1c2SMaxim Levitsky 6519fa9c1c2SMaxim Levitsky /* 6529fa9c1c2SMaxim Levitsky * The cipher_mode header contains a string that we have 6539fa9c1c2SMaxim Levitsky * to further parse, of the format 6549fa9c1c2SMaxim Levitsky * 6559fa9c1c2SMaxim Levitsky * <cipher-mode>-<iv-generator>[:<iv-hash>] 6569fa9c1c2SMaxim Levitsky * 6579fa9c1c2SMaxim Levitsky * eg cbc-essiv:sha256, cbc-plain64 6589fa9c1c2SMaxim Levitsky */ 6599fa9c1c2SMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 6609fa9c1c2SMaxim Levitsky if (!ivgen_name) { 6619fa9c1c2SMaxim Levitsky error_setg(errp, "Unexpected cipher mode string format %s", 6629fa9c1c2SMaxim Levitsky luks->header.cipher_mode); 6639fa9c1c2SMaxim Levitsky return -1; 6649fa9c1c2SMaxim Levitsky } 6659fa9c1c2SMaxim Levitsky *ivgen_name = '\0'; 6669fa9c1c2SMaxim Levitsky ivgen_name++; 6679fa9c1c2SMaxim Levitsky 6689fa9c1c2SMaxim Levitsky ivhash_name = strchr(ivgen_name, ':'); 6699fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6709fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = 0; 6719fa9c1c2SMaxim Levitsky } else { 6729fa9c1c2SMaxim Levitsky *ivhash_name = '\0'; 6739fa9c1c2SMaxim Levitsky ivhash_name++; 6749fa9c1c2SMaxim Levitsky 6759fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 6769fa9c1c2SMaxim Levitsky &local_err); 6779fa9c1c2SMaxim Levitsky if (local_err) { 6789fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6799fa9c1c2SMaxim Levitsky return -1; 6809fa9c1c2SMaxim Levitsky } 6819fa9c1c2SMaxim Levitsky } 6829fa9c1c2SMaxim Levitsky 6839fa9c1c2SMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 6849fa9c1c2SMaxim Levitsky &local_err); 6859fa9c1c2SMaxim Levitsky if (local_err) { 6869fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6879fa9c1c2SMaxim Levitsky return -1; 6889fa9c1c2SMaxim Levitsky } 6899fa9c1c2SMaxim Levitsky 6909fa9c1c2SMaxim Levitsky luks->cipher_alg = 6919fa9c1c2SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 6929fa9c1c2SMaxim Levitsky luks->cipher_mode, 6939fa9c1c2SMaxim Levitsky luks->header.master_key_len, 6949fa9c1c2SMaxim Levitsky &local_err); 6959fa9c1c2SMaxim Levitsky if (local_err) { 6969fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6979fa9c1c2SMaxim Levitsky return -1; 6989fa9c1c2SMaxim Levitsky } 6999fa9c1c2SMaxim Levitsky 7009fa9c1c2SMaxim Levitsky luks->hash_alg = 7019fa9c1c2SMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 7029fa9c1c2SMaxim Levitsky &local_err); 7039fa9c1c2SMaxim Levitsky if (local_err) { 7049fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 7059fa9c1c2SMaxim Levitsky return -1; 7069fa9c1c2SMaxim Levitsky } 7079fa9c1c2SMaxim Levitsky 7089fa9c1c2SMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 7099fa9c1c2SMaxim Levitsky &local_err); 7109fa9c1c2SMaxim Levitsky if (local_err) { 7119fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 7129fa9c1c2SMaxim Levitsky return -1; 7139fa9c1c2SMaxim Levitsky } 7149fa9c1c2SMaxim Levitsky 7159fa9c1c2SMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 7169fa9c1c2SMaxim Levitsky if (!ivhash_name) { 7179fa9c1c2SMaxim Levitsky error_setg(errp, "Missing IV generator hash specification"); 7189fa9c1c2SMaxim Levitsky return -1; 7199fa9c1c2SMaxim Levitsky } 7209fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = 7219fa9c1c2SMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 7229fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg, 7239fa9c1c2SMaxim Levitsky &local_err); 7249fa9c1c2SMaxim Levitsky if (local_err) { 7259fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 7269fa9c1c2SMaxim Levitsky return -1; 7279fa9c1c2SMaxim Levitsky } 7289fa9c1c2SMaxim Levitsky } else { 7299fa9c1c2SMaxim Levitsky 7309fa9c1c2SMaxim Levitsky /* 7319fa9c1c2SMaxim Levitsky * Note we parsed the ivhash_name earlier in the cipher_mode 7329fa9c1c2SMaxim Levitsky * spec string even with plain/plain64 ivgens, but we 7339fa9c1c2SMaxim Levitsky * will ignore it, since it is irrelevant for these ivgens. 7349fa9c1c2SMaxim Levitsky * This is for compat with dm-crypt which will silently 7359fa9c1c2SMaxim Levitsky * ignore hash names with these ivgens rather than report 7369fa9c1c2SMaxim Levitsky * an error about the invalid usage 7379fa9c1c2SMaxim Levitsky */ 7389fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 7399fa9c1c2SMaxim Levitsky } 7409fa9c1c2SMaxim Levitsky return 0; 7419fa9c1c2SMaxim Levitsky } 7429fa9c1c2SMaxim Levitsky 7439fa9c1c2SMaxim Levitsky /* 7443994a7c9SMaxim Levitsky * Given a key slot, user password, and the master key, 7453994a7c9SMaxim Levitsky * will store the encrypted master key there, and update the 7463994a7c9SMaxim Levitsky * in-memory header. User must then write the in-memory header 7473994a7c9SMaxim Levitsky * 7483994a7c9SMaxim Levitsky * Returns: 7493994a7c9SMaxim Levitsky * 0 if the keyslot was written successfully 7503994a7c9SMaxim Levitsky * with the provided password 7513994a7c9SMaxim Levitsky * -1 if a fatal error occurred while storing the key 7523994a7c9SMaxim Levitsky */ 7533994a7c9SMaxim Levitsky static int 7543994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block, 7553994a7c9SMaxim Levitsky unsigned int slot_idx, 7563994a7c9SMaxim Levitsky const char *password, 7573994a7c9SMaxim Levitsky uint8_t *masterkey, 7583994a7c9SMaxim Levitsky uint64_t iter_time, 7593994a7c9SMaxim Levitsky QCryptoBlockWriteFunc writefunc, 7603994a7c9SMaxim Levitsky void *opaque, 7613994a7c9SMaxim Levitsky Error **errp) 7623994a7c9SMaxim Levitsky { 7633994a7c9SMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 764557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 7653994a7c9SMaxim Levitsky g_autofree uint8_t *splitkey = NULL; 7663994a7c9SMaxim Levitsky size_t splitkeylen; 7673994a7c9SMaxim Levitsky g_autofree uint8_t *slotkey = NULL; 7683994a7c9SMaxim Levitsky g_autoptr(QCryptoCipher) cipher = NULL; 7693994a7c9SMaxim Levitsky g_autoptr(QCryptoIVGen) ivgen = NULL; 7703994a7c9SMaxim Levitsky Error *local_err = NULL; 7713994a7c9SMaxim Levitsky uint64_t iters; 7723994a7c9SMaxim Levitsky int ret = -1; 7733994a7c9SMaxim Levitsky 774557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 775557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 7763994a7c9SMaxim Levitsky if (qcrypto_random_bytes(slot->salt, 7773994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7783994a7c9SMaxim Levitsky errp) < 0) { 7793994a7c9SMaxim Levitsky goto cleanup; 7803994a7c9SMaxim Levitsky } 7813994a7c9SMaxim Levitsky 7823994a7c9SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 7833994a7c9SMaxim Levitsky 7843994a7c9SMaxim Levitsky /* 7853994a7c9SMaxim Levitsky * Determine how many iterations are required to 7863994a7c9SMaxim Levitsky * hash the user password while consuming 1 second of compute 7873994a7c9SMaxim Levitsky * time 7883994a7c9SMaxim Levitsky */ 7893994a7c9SMaxim Levitsky iters = qcrypto_pbkdf2_count_iters(luks->hash_alg, 7903994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7913994a7c9SMaxim Levitsky slot->salt, 7923994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7933994a7c9SMaxim Levitsky luks->header.master_key_len, 7943994a7c9SMaxim Levitsky &local_err); 7953994a7c9SMaxim Levitsky if (local_err) { 7963994a7c9SMaxim Levitsky error_propagate(errp, local_err); 7973994a7c9SMaxim Levitsky goto cleanup; 7983994a7c9SMaxim Levitsky } 7993994a7c9SMaxim Levitsky 8003994a7c9SMaxim Levitsky if (iters > (ULLONG_MAX / iter_time)) { 8013994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 8023994a7c9SMaxim Levitsky "PBKDF iterations %llu too large to scale", 8033994a7c9SMaxim Levitsky (unsigned long long)iters); 8043994a7c9SMaxim Levitsky goto cleanup; 8053994a7c9SMaxim Levitsky } 8063994a7c9SMaxim Levitsky 8073994a7c9SMaxim Levitsky /* iter_time was in millis, but count_iters reported for secs */ 8083994a7c9SMaxim Levitsky iters = iters * iter_time / 1000; 8093994a7c9SMaxim Levitsky 8103994a7c9SMaxim Levitsky if (iters > UINT32_MAX) { 8113994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 8123994a7c9SMaxim Levitsky "PBKDF iterations %llu larger than %u", 8133994a7c9SMaxim Levitsky (unsigned long long)iters, UINT32_MAX); 8143994a7c9SMaxim Levitsky goto cleanup; 8153994a7c9SMaxim Levitsky } 8163994a7c9SMaxim Levitsky 8173994a7c9SMaxim Levitsky slot->iterations = 8183994a7c9SMaxim Levitsky MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 8193994a7c9SMaxim Levitsky 8203994a7c9SMaxim Levitsky 8213994a7c9SMaxim Levitsky /* 8223994a7c9SMaxim Levitsky * Generate a key that we'll use to encrypt the master 8233994a7c9SMaxim Levitsky * key, from the user's password 8243994a7c9SMaxim Levitsky */ 8253994a7c9SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 8263994a7c9SMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 8273994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 8283994a7c9SMaxim Levitsky slot->salt, 8293994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 8303994a7c9SMaxim Levitsky slot->iterations, 8313994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 8323994a7c9SMaxim Levitsky errp) < 0) { 8333994a7c9SMaxim Levitsky goto cleanup; 8343994a7c9SMaxim Levitsky } 8353994a7c9SMaxim Levitsky 8363994a7c9SMaxim Levitsky 8373994a7c9SMaxim Levitsky /* 8383994a7c9SMaxim Levitsky * Setup the encryption objects needed to encrypt the 8393994a7c9SMaxim Levitsky * master key material 8403994a7c9SMaxim Levitsky */ 8413994a7c9SMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 8423994a7c9SMaxim Levitsky luks->cipher_mode, 8433994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 8443994a7c9SMaxim Levitsky errp); 8453994a7c9SMaxim Levitsky if (!cipher) { 8463994a7c9SMaxim Levitsky goto cleanup; 8473994a7c9SMaxim Levitsky } 8483994a7c9SMaxim Levitsky 8493994a7c9SMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 8503994a7c9SMaxim Levitsky luks->ivgen_cipher_alg, 8513994a7c9SMaxim Levitsky luks->ivgen_hash_alg, 8523994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 8533994a7c9SMaxim Levitsky errp); 8543994a7c9SMaxim Levitsky if (!ivgen) { 8553994a7c9SMaxim Levitsky goto cleanup; 8563994a7c9SMaxim Levitsky } 8573994a7c9SMaxim Levitsky 8583994a7c9SMaxim Levitsky /* 8593994a7c9SMaxim Levitsky * Before storing the master key, we need to vastly 8603994a7c9SMaxim Levitsky * increase its size, as protection against forensic 8613994a7c9SMaxim Levitsky * disk data recovery 8623994a7c9SMaxim Levitsky */ 8633994a7c9SMaxim Levitsky splitkey = g_new0(uint8_t, splitkeylen); 8643994a7c9SMaxim Levitsky 8653994a7c9SMaxim Levitsky if (qcrypto_afsplit_encode(luks->hash_alg, 8663994a7c9SMaxim Levitsky luks->header.master_key_len, 8673994a7c9SMaxim Levitsky slot->stripes, 8683994a7c9SMaxim Levitsky masterkey, 8693994a7c9SMaxim Levitsky splitkey, 8703994a7c9SMaxim Levitsky errp) < 0) { 8713994a7c9SMaxim Levitsky goto cleanup; 8723994a7c9SMaxim Levitsky } 8733994a7c9SMaxim Levitsky 8743994a7c9SMaxim Levitsky /* 8753994a7c9SMaxim Levitsky * Now we encrypt the split master key with the key generated 8763994a7c9SMaxim Levitsky * from the user's password, before storing it 8773994a7c9SMaxim Levitsky */ 8783994a7c9SMaxim Levitsky if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 8793994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8803994a7c9SMaxim Levitsky 0, 8813994a7c9SMaxim Levitsky splitkey, 8823994a7c9SMaxim Levitsky splitkeylen, 8833994a7c9SMaxim Levitsky errp) < 0) { 8843994a7c9SMaxim Levitsky goto cleanup; 8853994a7c9SMaxim Levitsky } 8863994a7c9SMaxim Levitsky 8873994a7c9SMaxim Levitsky /* Write out the slot's master key material. */ 8883994a7c9SMaxim Levitsky if (writefunc(block, 8893994a7c9SMaxim Levitsky slot->key_offset_sector * 8903994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8913994a7c9SMaxim Levitsky splitkey, splitkeylen, 8923994a7c9SMaxim Levitsky opaque, 893757dda54SAlberto Faria errp) < 0) { 8943994a7c9SMaxim Levitsky goto cleanup; 8953994a7c9SMaxim Levitsky } 8963994a7c9SMaxim Levitsky 8973994a7c9SMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 8983994a7c9SMaxim Levitsky 8993994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) { 9003994a7c9SMaxim Levitsky goto cleanup; 9013994a7c9SMaxim Levitsky } 9023994a7c9SMaxim Levitsky 9033994a7c9SMaxim Levitsky ret = 0; 9043994a7c9SMaxim Levitsky 9053994a7c9SMaxim Levitsky cleanup: 9063994a7c9SMaxim Levitsky if (slotkey) { 9073994a7c9SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 9083994a7c9SMaxim Levitsky } 9093994a7c9SMaxim Levitsky if (splitkey) { 9103994a7c9SMaxim Levitsky memset(splitkey, 0, splitkeylen); 9113994a7c9SMaxim Levitsky } 9123994a7c9SMaxim Levitsky return ret; 9133994a7c9SMaxim Levitsky } 9143994a7c9SMaxim Levitsky 9153994a7c9SMaxim Levitsky /* 9163e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 9173e308f20SDaniel P. Berrange * the master encryption key from the key slot. 9183e308f20SDaniel P. Berrange * 9193e308f20SDaniel P. Berrange * Returns: 9203e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 9213e308f20SDaniel P. Berrange * with the provided password 9223e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 9233e308f20SDaniel P. Berrange * with the provided password 9243e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 9253e308f20SDaniel P. Berrange */ 9263e308f20SDaniel P. Berrange static int 9273e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 9287e60a6f5SMaxim Levitsky size_t slot_idx, 9293e308f20SDaniel P. Berrange const char *password, 9303e308f20SDaniel P. Berrange uint8_t *masterkey, 9313e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 9323e308f20SDaniel P. Berrange void *opaque, 9333e308f20SDaniel P. Berrange Error **errp) 9343e308f20SDaniel P. Berrange { 9353e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 936557d2bdcSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot; 93757b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 9383e308f20SDaniel P. Berrange size_t splitkeylen; 93957b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 940757dda54SAlberto Faria int rv; 94157b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 9423e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 94357b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 9443e308f20SDaniel P. Berrange size_t niv; 9453e308f20SDaniel P. Berrange 946557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 947557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 9483e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 9493e308f20SDaniel P. Berrange return 0; 9503e308f20SDaniel P. Berrange } 9513e308f20SDaniel P. Berrange 9521ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 9533e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 9541ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 9553e308f20SDaniel P. Berrange 9563e308f20SDaniel P. Berrange /* 9573e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 9583e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 9593e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 9603e308f20SDaniel P. Berrange * the key is correct and validate the results of 9613e308f20SDaniel P. Berrange * decryption later. 9623e308f20SDaniel P. Berrange */ 9639d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 9643e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 9653e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 9663e308f20SDaniel P. Berrange slot->iterations, 9671ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 9683e308f20SDaniel P. Berrange errp) < 0) { 96957b9f113SDaniel P. Berrangé return -1; 9703e308f20SDaniel P. Berrange } 9713e308f20SDaniel P. Berrange 9723e308f20SDaniel P. Berrange /* 9733e308f20SDaniel P. Berrange * We need to read the master key material from the 9743e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 9753e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 9763e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 9773e308f20SDaniel P. Berrange * then encrypted. 9783e308f20SDaniel P. Berrange */ 9793e308f20SDaniel P. Berrange rv = readfunc(block, 980f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9813e308f20SDaniel P. Berrange splitkey, splitkeylen, 982e4a3507eSDaniel P. Berrange opaque, 98337509233SFam Zheng errp); 9843e308f20SDaniel P. Berrange if (rv < 0) { 98557b9f113SDaniel P. Berrangé return -1; 9863e308f20SDaniel P. Berrange } 9873e308f20SDaniel P. Berrange 9883e308f20SDaniel P. Berrange 9893e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 9903e308f20SDaniel P. Berrange * the split master key material */ 9919d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 9929d80e59dSMaxim Levitsky luks->cipher_mode, 9939d80e59dSMaxim Levitsky possiblekey, 9949d80e59dSMaxim Levitsky luks->header.master_key_len, 9953e308f20SDaniel P. Berrange errp); 9963e308f20SDaniel P. Berrange if (!cipher) { 99757b9f113SDaniel P. Berrangé return -1; 9983e308f20SDaniel P. Berrange } 9993e308f20SDaniel P. Berrange 10009d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 10019d80e59dSMaxim Levitsky luks->cipher_mode); 10029d80e59dSMaxim Levitsky 10039d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 10049d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 10059d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 10069d80e59dSMaxim Levitsky possiblekey, 10079d80e59dSMaxim Levitsky luks->header.master_key_len, 10083e308f20SDaniel P. Berrange errp); 10093e308f20SDaniel P. Berrange if (!ivgen) { 101057b9f113SDaniel P. Berrangé return -1; 10113e308f20SDaniel P. Berrange } 10123e308f20SDaniel P. Berrange 10133e308f20SDaniel P. Berrange 10143e308f20SDaniel P. Berrange /* 10153e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 10163e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 10173e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 10183e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 10193e308f20SDaniel P. Berrange * key crosses a sector boundary. 10203e308f20SDaniel P. Berrange */ 10210270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 10223e308f20SDaniel P. Berrange niv, 10233e308f20SDaniel P. Berrange ivgen, 10243e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 10253e308f20SDaniel P. Berrange 0, 10263e308f20SDaniel P. Berrange splitkey, 10273e308f20SDaniel P. Berrange splitkeylen, 10283e308f20SDaniel P. Berrange errp) < 0) { 102957b9f113SDaniel P. Berrangé return -1; 10303e308f20SDaniel P. Berrange } 10313e308f20SDaniel P. Berrange 10323e308f20SDaniel P. Berrange /* 10333e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 10343e308f20SDaniel P. Berrange * it back together to get the actual master key. 10353e308f20SDaniel P. Berrange */ 10369d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 10371ddd52e4SMaxim Levitsky luks->header.master_key_len, 10383e308f20SDaniel P. Berrange slot->stripes, 10393e308f20SDaniel P. Berrange splitkey, 10403e308f20SDaniel P. Berrange masterkey, 10413e308f20SDaniel P. Berrange errp) < 0) { 104257b9f113SDaniel P. Berrangé return -1; 10433e308f20SDaniel P. Berrange } 10443e308f20SDaniel P. Berrange 10453e308f20SDaniel P. Berrange 10463e308f20SDaniel P. Berrange /* 10473e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 10483e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 10493e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 10503e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 10513e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 10523e308f20SDaniel P. Berrange * header 10533e308f20SDaniel P. Berrange */ 10549d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 10551ddd52e4SMaxim Levitsky masterkey, 10561ddd52e4SMaxim Levitsky luks->header.master_key_len, 10573e308f20SDaniel P. Berrange luks->header.master_key_salt, 10583e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10593e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10601ddd52e4SMaxim Levitsky keydigest, 10611ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 10623e308f20SDaniel P. Berrange errp) < 0) { 106357b9f113SDaniel P. Berrangé return -1; 10643e308f20SDaniel P. Berrange } 10653e308f20SDaniel P. Berrange 10663e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 10673e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 10683e308f20SDaniel P. Berrange /* Success, we got the right master key */ 106957b9f113SDaniel P. Berrangé return 1; 10703e308f20SDaniel P. Berrange } 10713e308f20SDaniel P. Berrange 10723e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 10733e308f20SDaniel P. Berrange * tell caller to try another slot */ 107457b9f113SDaniel P. Berrangé return 0; 10753e308f20SDaniel P. Berrange } 10763e308f20SDaniel P. Berrange 10773e308f20SDaniel P. Berrange 10783e308f20SDaniel P. Berrange /* 10793e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 10803e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 10813e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 10823e308f20SDaniel P. Berrange * 10833e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 10843e308f20SDaniel P. Berrange */ 10853e308f20SDaniel P. Berrange static int 10863e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 10873e308f20SDaniel P. Berrange const char *password, 10881ddd52e4SMaxim Levitsky uint8_t *masterkey, 10893e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 10903e308f20SDaniel P. Berrange void *opaque, 10913e308f20SDaniel P. Berrange Error **errp) 10923e308f20SDaniel P. Berrange { 10933e308f20SDaniel P. Berrange size_t i; 10943e308f20SDaniel P. Berrange int rv; 10953e308f20SDaniel P. Berrange 10963e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10973e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 10987e60a6f5SMaxim Levitsky i, 10993e308f20SDaniel P. Berrange password, 11001ddd52e4SMaxim Levitsky masterkey, 11013e308f20SDaniel P. Berrange readfunc, 11023e308f20SDaniel P. Berrange opaque, 11033e308f20SDaniel P. Berrange errp); 11043e308f20SDaniel P. Berrange if (rv < 0) { 11053e308f20SDaniel P. Berrange goto error; 11063e308f20SDaniel P. Berrange } 11073e308f20SDaniel P. Berrange if (rv == 1) { 11083e308f20SDaniel P. Berrange return 0; 11093e308f20SDaniel P. Berrange } 11103e308f20SDaniel P. Berrange } 11113e308f20SDaniel P. Berrange 11123e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 11133e308f20SDaniel P. Berrange error: 11143e308f20SDaniel P. Berrange return -1; 11153e308f20SDaniel P. Berrange } 11163e308f20SDaniel P. Berrange 1117557d2bdcSMaxim Levitsky /* 1118557d2bdcSMaxim Levitsky * Returns true if a slot i is marked as active 1119557d2bdcSMaxim Levitsky * (contains encrypted copy of the master key) 1120557d2bdcSMaxim Levitsky */ 1121557d2bdcSMaxim Levitsky static bool 1122557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, 1123557d2bdcSMaxim Levitsky unsigned int slot_idx) 1124557d2bdcSMaxim Levitsky { 1125557d2bdcSMaxim Levitsky uint32_t val; 1126557d2bdcSMaxim Levitsky 1127557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1128557d2bdcSMaxim Levitsky val = luks->header.key_slots[slot_idx].active; 1129557d2bdcSMaxim Levitsky return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1130557d2bdcSMaxim Levitsky } 1131557d2bdcSMaxim Levitsky 1132557d2bdcSMaxim Levitsky /* 1133557d2bdcSMaxim Levitsky * Returns the number of slots that are marked as active 1134557d2bdcSMaxim Levitsky * (slots that contain encrypted copy of the master key) 1135557d2bdcSMaxim Levitsky */ 1136557d2bdcSMaxim Levitsky static unsigned int 1137557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) 1138557d2bdcSMaxim Levitsky { 1139557d2bdcSMaxim Levitsky size_t i = 0; 1140557d2bdcSMaxim Levitsky unsigned int ret = 0; 1141557d2bdcSMaxim Levitsky 1142557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1143557d2bdcSMaxim Levitsky if (qcrypto_block_luks_slot_active(luks, i)) { 1144557d2bdcSMaxim Levitsky ret++; 1145557d2bdcSMaxim Levitsky } 1146557d2bdcSMaxim Levitsky } 1147557d2bdcSMaxim Levitsky return ret; 1148557d2bdcSMaxim Levitsky } 1149557d2bdcSMaxim Levitsky 1150557d2bdcSMaxim Levitsky /* 1151557d2bdcSMaxim Levitsky * Finds first key slot which is not active 1152557d2bdcSMaxim Levitsky * Returns the key slot index, or -1 if it doesn't exist 1153557d2bdcSMaxim Levitsky */ 1154557d2bdcSMaxim Levitsky static int 1155557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) 1156557d2bdcSMaxim Levitsky { 1157557d2bdcSMaxim Levitsky size_t i; 1158557d2bdcSMaxim Levitsky 1159557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1160557d2bdcSMaxim Levitsky if (!qcrypto_block_luks_slot_active(luks, i)) { 1161557d2bdcSMaxim Levitsky return i; 1162557d2bdcSMaxim Levitsky } 1163557d2bdcSMaxim Levitsky } 1164557d2bdcSMaxim Levitsky return -1; 1165557d2bdcSMaxim Levitsky } 1166557d2bdcSMaxim Levitsky 1167557d2bdcSMaxim Levitsky /* 1168557d2bdcSMaxim Levitsky * Erases an keyslot given its index 1169557d2bdcSMaxim Levitsky * Returns: 1170557d2bdcSMaxim Levitsky * 0 if the keyslot was erased successfully 1171557d2bdcSMaxim Levitsky * -1 if a error occurred while erasing the keyslot 1172557d2bdcSMaxim Levitsky * 1173557d2bdcSMaxim Levitsky */ 1174557d2bdcSMaxim Levitsky static int 1175557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block, 1176557d2bdcSMaxim Levitsky unsigned int slot_idx, 1177557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1178557d2bdcSMaxim Levitsky void *opaque, 1179557d2bdcSMaxim Levitsky Error **errp) 1180557d2bdcSMaxim Levitsky { 1181557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1182557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 1183557d2bdcSMaxim Levitsky g_autofree uint8_t *garbagesplitkey = NULL; 1184557d2bdcSMaxim Levitsky size_t splitkeylen; 1185557d2bdcSMaxim Levitsky size_t i; 1186557d2bdcSMaxim Levitsky Error *local_err = NULL; 1187557d2bdcSMaxim Levitsky int ret; 1188557d2bdcSMaxim Levitsky 1189557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1190557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 1191557d2bdcSMaxim Levitsky 1192557d2bdcSMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 1193557d2bdcSMaxim Levitsky assert(splitkeylen > 0); 1194557d2bdcSMaxim Levitsky 1195557d2bdcSMaxim Levitsky garbagesplitkey = g_new0(uint8_t, splitkeylen); 1196557d2bdcSMaxim Levitsky 1197557d2bdcSMaxim Levitsky /* Reset the key slot header */ 1198557d2bdcSMaxim Levitsky memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); 1199557d2bdcSMaxim Levitsky slot->iterations = 0; 1200557d2bdcSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 1201557d2bdcSMaxim Levitsky 1202557d2bdcSMaxim Levitsky ret = qcrypto_block_luks_store_header(block, writefunc, 1203557d2bdcSMaxim Levitsky opaque, &local_err); 1204557d2bdcSMaxim Levitsky 1205557d2bdcSMaxim Levitsky if (ret < 0) { 1206557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1207557d2bdcSMaxim Levitsky } 1208557d2bdcSMaxim Levitsky /* 1209557d2bdcSMaxim Levitsky * Now try to erase the key material, even if the header 1210557d2bdcSMaxim Levitsky * update failed 1211557d2bdcSMaxim Levitsky */ 1212557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { 1213557d2bdcSMaxim Levitsky if (qcrypto_random_bytes(garbagesplitkey, 1214557d2bdcSMaxim Levitsky splitkeylen, &local_err) < 0) { 1215557d2bdcSMaxim Levitsky /* 1216557d2bdcSMaxim Levitsky * If we failed to get the random data, still write 1217557d2bdcSMaxim Levitsky * at least zeros to the key slot at least once 1218557d2bdcSMaxim Levitsky */ 1219557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1220557d2bdcSMaxim Levitsky 1221557d2bdcSMaxim Levitsky if (i > 0) { 1222557d2bdcSMaxim Levitsky return -1; 1223557d2bdcSMaxim Levitsky } 1224557d2bdcSMaxim Levitsky } 1225557d2bdcSMaxim Levitsky if (writefunc(block, 1226557d2bdcSMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 1227557d2bdcSMaxim Levitsky garbagesplitkey, 1228557d2bdcSMaxim Levitsky splitkeylen, 1229557d2bdcSMaxim Levitsky opaque, 1230757dda54SAlberto Faria &local_err) < 0) { 1231557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1232557d2bdcSMaxim Levitsky return -1; 1233557d2bdcSMaxim Levitsky } 1234557d2bdcSMaxim Levitsky } 1235557d2bdcSMaxim Levitsky return ret; 1236557d2bdcSMaxim Levitsky } 12373e308f20SDaniel P. Berrange 12383e308f20SDaniel P. Berrange static int 12393e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 12403e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 12411cd9a787SDaniel P. Berrange const char *optprefix, 12423e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 12433e308f20SDaniel P. Berrange void *opaque, 12443e308f20SDaniel P. Berrange unsigned int flags, 1245c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 12463e308f20SDaniel P. Berrange Error **errp) 12473e308f20SDaniel P. Berrange { 12489d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 124957b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 125057b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 12513e308f20SDaniel P. Berrange 12523e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12533e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 12541cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 12551cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 12563e308f20SDaniel P. Berrange return -1; 12573e308f20SDaniel P. Berrange } 12583e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 12593e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 12603e308f20SDaniel P. Berrange if (!password) { 12613e308f20SDaniel P. Berrange return -1; 12623e308f20SDaniel P. Berrange } 12633e308f20SDaniel P. Berrange } 12643e308f20SDaniel P. Berrange 12653e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 12663e308f20SDaniel P. Berrange block->opaque = luks; 1267557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 12683e308f20SDaniel P. Berrange 1269dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 12703e308f20SDaniel P. Berrange goto fail; 12713e308f20SDaniel P. Berrange } 12723e308f20SDaniel P. Berrange 12739fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_check_header(luks, errp) < 0) { 12743e308f20SDaniel P. Berrange goto fail; 12753e308f20SDaniel P. Berrange } 12763e308f20SDaniel P. Berrange 12779fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_parse_header(luks, errp) < 0) { 12783e308f20SDaniel P. Berrange goto fail; 12793e308f20SDaniel P. Berrange } 12803e308f20SDaniel P. Berrange 12813e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12823e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 12833e308f20SDaniel P. Berrange * and unlock the master key from that slot. 12843e308f20SDaniel P. Berrange */ 12851ddd52e4SMaxim Levitsky 12861ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 12871ddd52e4SMaxim Levitsky 12883e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 12893e308f20SDaniel P. Berrange password, 12901ddd52e4SMaxim Levitsky masterkey, 12913e308f20SDaniel P. Berrange readfunc, opaque, 12923e308f20SDaniel P. Berrange errp) < 0) { 12933e308f20SDaniel P. Berrange goto fail; 12943e308f20SDaniel P. Berrange } 12953e308f20SDaniel P. Berrange 12963e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 12973e308f20SDaniel P. Berrange * block device payload decryption objects 12983e308f20SDaniel P. Berrange */ 12999d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 13009d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 13019d80e59dSMaxim Levitsky luks->cipher_mode); 13029d80e59dSMaxim Levitsky 13039d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 13049d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 13059d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 13061ddd52e4SMaxim Levitsky masterkey, 13071ddd52e4SMaxim Levitsky luks->header.master_key_len, 13083e308f20SDaniel P. Berrange errp); 13093e308f20SDaniel P. Berrange if (!block->ivgen) { 13103e308f20SDaniel P. Berrange goto fail; 13113e308f20SDaniel P. Berrange } 13123e308f20SDaniel P. Berrange 131361dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 13149d80e59dSMaxim Levitsky luks->cipher_alg, 13159d80e59dSMaxim Levitsky luks->cipher_mode, 13161ddd52e4SMaxim Levitsky masterkey, 13171ddd52e4SMaxim Levitsky luks->header.master_key_len, 13181ddd52e4SMaxim Levitsky n_threads, 131961dd8a9aSMaxim Levitsky errp) < 0) { 13203e308f20SDaniel P. Berrange goto fail; 13213e308f20SDaniel P. Berrange } 13223e308f20SDaniel P. Berrange } 13233e308f20SDaniel P. Berrange 1324850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1325f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1326850f49deSDaniel P. Berrange block->sector_size; 13273e308f20SDaniel P. Berrange 13283e308f20SDaniel P. Berrange return 0; 13293e308f20SDaniel P. Berrange 13303e308f20SDaniel P. Berrange fail: 1331c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 13323e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 1333557d2bdcSMaxim Levitsky g_free(luks->secret); 13343e308f20SDaniel P. Berrange g_free(luks); 133561dd8a9aSMaxim Levitsky return -1; 13363e308f20SDaniel P. Berrange } 13373e308f20SDaniel P. Berrange 13383e308f20SDaniel P. Berrange 13392ef950f9SFam Zheng static void 13402ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 13413e308f20SDaniel P. Berrange { 13422ef950f9SFam Zheng QemuUUID uuid; 13432ef950f9SFam Zheng qemu_uuid_generate(&uuid); 13442ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 13453e308f20SDaniel P. Berrange } 13463e308f20SDaniel P. Berrange 13473e308f20SDaniel P. Berrange static int 13483e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 13493e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 13501cd9a787SDaniel P. Berrange const char *optprefix, 13513e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 13523e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 13533e308f20SDaniel P. Berrange void *opaque, 13543e308f20SDaniel P. Berrange Error **errp) 13553e308f20SDaniel P. Berrange { 13563e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 13573e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 13583e308f20SDaniel P. Berrange Error *local_err = NULL; 135957b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 1360bd56a55aSMaxim Levitsky size_t header_sectors; 1361bd56a55aSMaxim Levitsky size_t split_key_sectors; 13623e308f20SDaniel P. Berrange size_t i; 136357b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 13643e308f20SDaniel P. Berrange const char *cipher_alg; 13653e308f20SDaniel P. Berrange const char *cipher_mode; 13663e308f20SDaniel P. Berrange const char *ivgen_alg; 13673e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 13683e308f20SDaniel P. Berrange const char *hash_alg; 136957b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 137059b060beSDaniel P. Berrange uint64_t iters; 13713e308f20SDaniel P. Berrange 13723e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 13733bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 1374557d2bdcSMaxim Levitsky luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 13753bd18890SDaniel P. Berrange } 13763e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 13773e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 13783e308f20SDaniel P. Berrange } 13793e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 13803e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 13813e308f20SDaniel P. Berrange } 13823e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 13833e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 13843e308f20SDaniel P. Berrange } 13853e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 13863e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 13873e308f20SDaniel P. Berrange } 13888b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 13898b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 13908b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 13918b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 13928b7cdba3SDaniel P. Berrange } 13938b7cdba3SDaniel P. Berrange } 13949d80e59dSMaxim Levitsky 13959d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 13969d80e59dSMaxim Levitsky block->opaque = luks; 13979d80e59dSMaxim Levitsky 13989d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 13999d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 14009d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 14019d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 14029d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 14039d80e59dSMaxim Levitsky 14049d80e59dSMaxim Levitsky 14058b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 14068b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 14078b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 14083e308f20SDaniel P. Berrange 14093e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 14101cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 14111cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 14129d80e59dSMaxim Levitsky goto error; 14133e308f20SDaniel P. Berrange } 1414557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 1415557d2bdcSMaxim Levitsky 14163e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 14173e308f20SDaniel P. Berrange if (!password) { 14189d80e59dSMaxim Levitsky goto error; 14193e308f20SDaniel P. Berrange } 14203e308f20SDaniel P. Berrange 14213e308f20SDaniel P. Berrange 14223e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 14233e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 14243e308f20SDaniel P. Berrange 14253e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 14263e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 14273e308f20SDaniel P. Berrange * it out to disk 14283e308f20SDaniel P. Berrange */ 14293e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 14302ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 14313e308f20SDaniel P. Berrange 14323e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 14333e308f20SDaniel P. Berrange errp); 14343e308f20SDaniel P. Berrange if (!cipher_alg) { 14353e308f20SDaniel P. Berrange goto error; 14363e308f20SDaniel P. Berrange } 14373e308f20SDaniel P. Berrange 1438977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 1439977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 14403e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 1441977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 14423e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 14433e308f20SDaniel P. Berrange ivgen_hash_alg); 14443e308f20SDaniel P. Berrange } else { 14453e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 14463e308f20SDaniel P. Berrange } 1447977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 14483e308f20SDaniel P. Berrange 14493e308f20SDaniel P. Berrange 14503e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 14513e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 14523e308f20SDaniel P. Berrange cipher_alg); 14533e308f20SDaniel P. Berrange goto error; 14543e308f20SDaniel P. Berrange } 14553e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 14563e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 14573e308f20SDaniel P. Berrange cipher_mode_spec); 14583e308f20SDaniel P. Berrange goto error; 14593e308f20SDaniel P. Berrange } 14603e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 14613e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 14623e308f20SDaniel P. Berrange hash_alg); 14633e308f20SDaniel P. Berrange goto error; 14643e308f20SDaniel P. Berrange } 14653e308f20SDaniel P. Berrange 14663e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 14679d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 14689d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 14693e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 14703e308f20SDaniel P. Berrange &local_err); 14713e308f20SDaniel P. Berrange if (local_err) { 14723e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14733e308f20SDaniel P. Berrange goto error; 14743e308f20SDaniel P. Berrange } 14753e308f20SDaniel P. Berrange } else { 14769d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 14773e308f20SDaniel P. Berrange } 14783e308f20SDaniel P. Berrange 14793e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 14803e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 14813e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 14823e308f20SDaniel P. Berrange 1483f0d3c362SMaxim Levitsky luks->header.master_key_len = 1484f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 1485f0d3c362SMaxim Levitsky 14863e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 1487f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 14883e308f20SDaniel P. Berrange } 14893e308f20SDaniel P. Berrange 14903e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 14913e308f20SDaniel P. Berrange * with PBKDF later 14923e308f20SDaniel P. Berrange */ 14933e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 14943e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 14953e308f20SDaniel P. Berrange errp) < 0) { 14963e308f20SDaniel P. Berrange goto error; 14973e308f20SDaniel P. Berrange } 14983e308f20SDaniel P. Berrange 14993e308f20SDaniel P. Berrange /* Generate random master key */ 1500f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 15013e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 1502f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 15033e308f20SDaniel P. Berrange goto error; 15043e308f20SDaniel P. Berrange } 15053e308f20SDaniel P. Berrange 15063e308f20SDaniel P. Berrange 15073e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1508c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1509c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1510f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 15113e308f20SDaniel P. Berrange goto error; 15123e308f20SDaniel P. Berrange } 15133e308f20SDaniel P. Berrange 15143e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 15153e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 15163e308f20SDaniel P. Berrange luks_opts.cipher_mode); 15173e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 15189d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 15193e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1520f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 15213e308f20SDaniel P. Berrange errp); 15223e308f20SDaniel P. Berrange 15233e308f20SDaniel P. Berrange if (!block->ivgen) { 15243e308f20SDaniel P. Berrange goto error; 15253e308f20SDaniel P. Berrange } 15263e308f20SDaniel P. Berrange 15273e308f20SDaniel P. Berrange 15283e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 15293e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 15303e308f20SDaniel P. Berrange */ 153159b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1532f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 15333e308f20SDaniel P. Berrange luks->header.master_key_salt, 15343e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1535e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 15363e308f20SDaniel P. Berrange &local_err); 15373e308f20SDaniel P. Berrange if (local_err) { 15383e308f20SDaniel P. Berrange error_propagate(errp, local_err); 15393e308f20SDaniel P. Berrange goto error; 15403e308f20SDaniel P. Berrange } 15413e308f20SDaniel P. Berrange 15423bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 15433bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 15443bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 15453bd18890SDaniel P. Berrange (unsigned long long)iters); 15463bd18890SDaniel P. Berrange goto error; 15473bd18890SDaniel P. Berrange } 15483bd18890SDaniel P. Berrange 15493bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 15503bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 15513bd18890SDaniel P. Berrange 15523e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 15533e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 15543e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 15553e308f20SDaniel P. Berrange * in total time to check all keys */ 155659b060beSDaniel P. Berrange iters /= 8; 155759b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 155859b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 155959b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 156059b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 156159b060beSDaniel P. Berrange goto error; 156259b060beSDaniel P. Berrange } 156359b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 156459b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 15653e308f20SDaniel P. Berrange 15663e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 15673e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 15683e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 15693e308f20SDaniel P. Berrange * valid master key 15703e308f20SDaniel P. Berrange */ 15713e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1572f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 15733e308f20SDaniel P. Berrange luks->header.master_key_salt, 15743e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 15753e308f20SDaniel P. Berrange luks->header.master_key_iterations, 15763e308f20SDaniel P. Berrange luks->header.master_key_digest, 15773e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 15783e308f20SDaniel P. Berrange errp) < 0) { 15793e308f20SDaniel P. Berrange goto error; 15803e308f20SDaniel P. Berrange } 15813e308f20SDaniel P. Berrange 1582bd56a55aSMaxim Levitsky /* start with the sector that follows the header*/ 1583bd56a55aSMaxim Levitsky header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 1584bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 15853e308f20SDaniel P. Berrange 1586bd56a55aSMaxim Levitsky split_key_sectors = 1587bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 1588bd56a55aSMaxim Levitsky header_sectors, 1589bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_STRIPES); 1590bd56a55aSMaxim Levitsky 15913e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1592bd56a55aSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i]; 1593bd56a55aSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 15943e308f20SDaniel P. Berrange 1595bd56a55aSMaxim Levitsky slot->key_offset_sector = header_sectors + i * split_key_sectors; 1596bd56a55aSMaxim Levitsky slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 15973e308f20SDaniel P. Berrange } 15983e308f20SDaniel P. Berrange 15993e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 16003e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 16013e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 16023e308f20SDaniel P. Berrange * to the nearest sector */ 1603bd56a55aSMaxim Levitsky luks->header.payload_offset_sector = header_sectors + 1604bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors; 16053e308f20SDaniel P. Berrange 1606850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1607f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1608850f49deSDaniel P. Berrange block->sector_size; 16093e308f20SDaniel P. Berrange 16103e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1611e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 16123e308f20SDaniel P. Berrange if (local_err) { 16133e308f20SDaniel P. Berrange error_propagate(errp, local_err); 16143e308f20SDaniel P. Berrange goto error; 16153e308f20SDaniel P. Berrange } 16163e308f20SDaniel P. Berrange 16173e308f20SDaniel P. Berrange 16183994a7c9SMaxim Levitsky /* populate the slot 0 with the password encrypted master key*/ 16193994a7c9SMaxim Levitsky /* This will also store the header */ 16203994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_key(block, 16213994a7c9SMaxim Levitsky 0, 16223994a7c9SMaxim Levitsky password, 16233994a7c9SMaxim Levitsky masterkey, 16243994a7c9SMaxim Levitsky luks_opts.iter_time, 16253994a7c9SMaxim Levitsky writefunc, 1626e4a3507eSDaniel P. Berrange opaque, 16273994a7c9SMaxim Levitsky errp) < 0) { 16283e308f20SDaniel P. Berrange goto error; 16293e308f20SDaniel P. Berrange } 16303e308f20SDaniel P. Berrange 1631f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 16323e308f20SDaniel P. Berrange 16333e308f20SDaniel P. Berrange return 0; 16343e308f20SDaniel P. Berrange 16353e308f20SDaniel P. Berrange error: 16363e308f20SDaniel P. Berrange if (masterkey) { 1637f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 16383e308f20SDaniel P. Berrange } 16393e308f20SDaniel P. Berrange 1640c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1641b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1642b640adcaSVladimir Sementsov-Ogievskiy 1643557d2bdcSMaxim Levitsky g_free(luks->secret); 16443e308f20SDaniel P. Berrange g_free(luks); 16453e308f20SDaniel P. Berrange return -1; 16463e308f20SDaniel P. Berrange } 16473e308f20SDaniel P. Berrange 1648557d2bdcSMaxim Levitsky static int 1649557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, 1650557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1651557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1652557d2bdcSMaxim Levitsky void *opaque, 1653557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1654557d2bdcSMaxim Levitsky bool force, 1655557d2bdcSMaxim Levitsky Error **errp) 1656557d2bdcSMaxim Levitsky { 1657557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1658557d2bdcSMaxim Levitsky uint64_t iter_time = opts_luks->has_iter_time ? 1659557d2bdcSMaxim Levitsky opts_luks->iter_time : 1660557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1661557d2bdcSMaxim Levitsky int keyslot; 1662557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1663557d2bdcSMaxim Levitsky g_autofree char *new_password = NULL; 1664557d2bdcSMaxim Levitsky g_autofree uint8_t *master_key = NULL; 1665557d2bdcSMaxim Levitsky 1666557d2bdcSMaxim Levitsky char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret; 1667557d2bdcSMaxim Levitsky 1668557d2bdcSMaxim Levitsky if (!opts_luks->has_new_secret) { 1669557d2bdcSMaxim Levitsky error_setg(errp, "'new-secret' is required to activate a keyslot"); 1670557d2bdcSMaxim Levitsky return -1; 1671557d2bdcSMaxim Levitsky } 1672557d2bdcSMaxim Levitsky if (opts_luks->has_old_secret) { 1673557d2bdcSMaxim Levitsky error_setg(errp, 1674557d2bdcSMaxim Levitsky "'old-secret' must not be given when activating keyslots"); 1675557d2bdcSMaxim Levitsky return -1; 1676557d2bdcSMaxim Levitsky } 1677557d2bdcSMaxim Levitsky 1678557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1679557d2bdcSMaxim Levitsky keyslot = opts_luks->keyslot; 1680557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1681557d2bdcSMaxim Levitsky error_setg(errp, 1682557d2bdcSMaxim Levitsky "Invalid keyslot %u specified, must be between 0 and %u", 1683557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1684557d2bdcSMaxim Levitsky return -1; 1685557d2bdcSMaxim Levitsky } 1686557d2bdcSMaxim Levitsky } else { 1687557d2bdcSMaxim Levitsky keyslot = qcrypto_block_luks_find_free_keyslot(luks); 1688557d2bdcSMaxim Levitsky if (keyslot == -1) { 1689557d2bdcSMaxim Levitsky error_setg(errp, 1690557d2bdcSMaxim Levitsky "Can't add a keyslot - all keyslots are in use"); 1691557d2bdcSMaxim Levitsky return -1; 1692557d2bdcSMaxim Levitsky } 1693557d2bdcSMaxim Levitsky } 1694557d2bdcSMaxim Levitsky 1695557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { 1696557d2bdcSMaxim Levitsky error_setg(errp, 1697557d2bdcSMaxim Levitsky "Refusing to overwrite active keyslot %i - " 1698557d2bdcSMaxim Levitsky "please erase it first", 1699557d2bdcSMaxim Levitsky keyslot); 1700557d2bdcSMaxim Levitsky return -1; 1701557d2bdcSMaxim Levitsky } 1702557d2bdcSMaxim Levitsky 1703557d2bdcSMaxim Levitsky /* Locate the password that will be used to retrieve the master key */ 1704557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(secret, errp); 1705557d2bdcSMaxim Levitsky if (!old_password) { 1706557d2bdcSMaxim Levitsky return -1; 1707557d2bdcSMaxim Levitsky } 1708557d2bdcSMaxim Levitsky 1709557d2bdcSMaxim Levitsky /* Retrieve the master key */ 1710557d2bdcSMaxim Levitsky master_key = g_new0(uint8_t, luks->header.master_key_len); 1711557d2bdcSMaxim Levitsky 1712557d2bdcSMaxim Levitsky if (qcrypto_block_luks_find_key(block, old_password, master_key, 1713557d2bdcSMaxim Levitsky readfunc, opaque, errp) < 0) { 1714557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to retrieve the master key"); 1715557d2bdcSMaxim Levitsky return -1; 1716557d2bdcSMaxim Levitsky } 1717557d2bdcSMaxim Levitsky 1718557d2bdcSMaxim Levitsky /* Locate the new password*/ 1719557d2bdcSMaxim Levitsky new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); 1720557d2bdcSMaxim Levitsky if (!new_password) { 1721557d2bdcSMaxim Levitsky return -1; 1722557d2bdcSMaxim Levitsky } 1723557d2bdcSMaxim Levitsky 1724557d2bdcSMaxim Levitsky /* Now set the new keyslots */ 1725557d2bdcSMaxim Levitsky if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, 1726557d2bdcSMaxim Levitsky iter_time, writefunc, opaque, errp)) { 1727557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to write to keyslot %i", keyslot); 1728557d2bdcSMaxim Levitsky return -1; 1729557d2bdcSMaxim Levitsky } 1730557d2bdcSMaxim Levitsky return 0; 1731557d2bdcSMaxim Levitsky } 1732557d2bdcSMaxim Levitsky 1733557d2bdcSMaxim Levitsky static int 1734557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, 1735557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1736557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1737557d2bdcSMaxim Levitsky void *opaque, 1738557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1739557d2bdcSMaxim Levitsky bool force, 1740557d2bdcSMaxim Levitsky Error **errp) 1741557d2bdcSMaxim Levitsky { 1742557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1743557d2bdcSMaxim Levitsky g_autofree uint8_t *tmpkey = NULL; 1744557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1745557d2bdcSMaxim Levitsky 1746557d2bdcSMaxim Levitsky if (opts_luks->has_new_secret) { 1747557d2bdcSMaxim Levitsky error_setg(errp, 1748557d2bdcSMaxim Levitsky "'new-secret' must not be given when erasing keyslots"); 1749557d2bdcSMaxim Levitsky return -1; 1750557d2bdcSMaxim Levitsky } 1751557d2bdcSMaxim Levitsky if (opts_luks->has_iter_time) { 1752557d2bdcSMaxim Levitsky error_setg(errp, 1753557d2bdcSMaxim Levitsky "'iter-time' must not be given when erasing keyslots"); 1754557d2bdcSMaxim Levitsky return -1; 1755557d2bdcSMaxim Levitsky } 1756557d2bdcSMaxim Levitsky if (opts_luks->has_secret) { 1757557d2bdcSMaxim Levitsky error_setg(errp, 1758557d2bdcSMaxim Levitsky "'secret' must not be given when erasing keyslots"); 1759557d2bdcSMaxim Levitsky return -1; 1760557d2bdcSMaxim Levitsky } 1761557d2bdcSMaxim Levitsky 1762557d2bdcSMaxim Levitsky /* Load the old password if given */ 1763557d2bdcSMaxim Levitsky if (opts_luks->has_old_secret) { 1764557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, 1765557d2bdcSMaxim Levitsky errp); 1766557d2bdcSMaxim Levitsky if (!old_password) { 1767557d2bdcSMaxim Levitsky return -1; 1768557d2bdcSMaxim Levitsky } 1769557d2bdcSMaxim Levitsky 1770557d2bdcSMaxim Levitsky /* 1771557d2bdcSMaxim Levitsky * Allocate a temporary key buffer that we will need when 1772557d2bdcSMaxim Levitsky * checking if slot matches the given old password 1773557d2bdcSMaxim Levitsky */ 1774557d2bdcSMaxim Levitsky tmpkey = g_new0(uint8_t, luks->header.master_key_len); 1775557d2bdcSMaxim Levitsky } 1776557d2bdcSMaxim Levitsky 1777557d2bdcSMaxim Levitsky /* Erase an explicitly given keyslot */ 1778557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1779557d2bdcSMaxim Levitsky int keyslot = opts_luks->keyslot; 1780557d2bdcSMaxim Levitsky 1781557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1782557d2bdcSMaxim Levitsky error_setg(errp, 1783557d2bdcSMaxim Levitsky "Invalid keyslot %i specified, must be between 0 and %i", 1784557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1785557d2bdcSMaxim Levitsky return -1; 1786557d2bdcSMaxim Levitsky } 1787557d2bdcSMaxim Levitsky 1788557d2bdcSMaxim Levitsky if (opts_luks->has_old_secret) { 1789557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1790557d2bdcSMaxim Levitsky keyslot, 1791557d2bdcSMaxim Levitsky old_password, 1792557d2bdcSMaxim Levitsky tmpkey, 1793557d2bdcSMaxim Levitsky readfunc, 1794557d2bdcSMaxim Levitsky opaque, 1795557d2bdcSMaxim Levitsky errp); 1796557d2bdcSMaxim Levitsky if (rv == -1) { 1797557d2bdcSMaxim Levitsky return -1; 1798557d2bdcSMaxim Levitsky } else if (rv == 0) { 1799557d2bdcSMaxim Levitsky error_setg(errp, 1800557d2bdcSMaxim Levitsky "Given keyslot %i doesn't contain the given " 1801557d2bdcSMaxim Levitsky "old password for erase operation", 1802557d2bdcSMaxim Levitsky keyslot); 1803557d2bdcSMaxim Levitsky return -1; 1804557d2bdcSMaxim Levitsky } 1805557d2bdcSMaxim Levitsky } 1806557d2bdcSMaxim Levitsky 1807557d2bdcSMaxim Levitsky if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { 1808557d2bdcSMaxim Levitsky error_setg(errp, 1809557d2bdcSMaxim Levitsky "Given keyslot %i is already erased (inactive) ", 1810557d2bdcSMaxim Levitsky keyslot); 1811557d2bdcSMaxim Levitsky return -1; 1812557d2bdcSMaxim Levitsky } 1813557d2bdcSMaxim Levitsky 1814557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { 1815557d2bdcSMaxim Levitsky error_setg(errp, 1816557d2bdcSMaxim Levitsky "Attempt to erase the only active keyslot %i " 1817557d2bdcSMaxim Levitsky "which will erase all the data in the image " 1818557d2bdcSMaxim Levitsky "irreversibly - refusing operation", 1819557d2bdcSMaxim Levitsky keyslot); 1820557d2bdcSMaxim Levitsky return -1; 1821557d2bdcSMaxim Levitsky } 1822557d2bdcSMaxim Levitsky 1823557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, keyslot, 1824557d2bdcSMaxim Levitsky writefunc, opaque, errp)) { 1825557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %i", keyslot); 1826557d2bdcSMaxim Levitsky return -1; 1827557d2bdcSMaxim Levitsky } 1828557d2bdcSMaxim Levitsky 1829557d2bdcSMaxim Levitsky /* Erase all keyslots that match the given old password */ 1830557d2bdcSMaxim Levitsky } else if (opts_luks->has_old_secret) { 1831557d2bdcSMaxim Levitsky 1832557d2bdcSMaxim Levitsky unsigned long slots_to_erase_bitmap = 0; 1833557d2bdcSMaxim Levitsky size_t i; 1834557d2bdcSMaxim Levitsky int slot_count; 1835557d2bdcSMaxim Levitsky 1836557d2bdcSMaxim Levitsky assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= 1837557d2bdcSMaxim Levitsky sizeof(slots_to_erase_bitmap) * 8); 1838557d2bdcSMaxim Levitsky 1839557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1840557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1841557d2bdcSMaxim Levitsky i, 1842557d2bdcSMaxim Levitsky old_password, 1843557d2bdcSMaxim Levitsky tmpkey, 1844557d2bdcSMaxim Levitsky readfunc, 1845557d2bdcSMaxim Levitsky opaque, 1846557d2bdcSMaxim Levitsky errp); 1847557d2bdcSMaxim Levitsky if (rv == -1) { 1848557d2bdcSMaxim Levitsky return -1; 1849557d2bdcSMaxim Levitsky } else if (rv == 1) { 1850557d2bdcSMaxim Levitsky bitmap_set(&slots_to_erase_bitmap, i, 1); 1851557d2bdcSMaxim Levitsky } 1852557d2bdcSMaxim Levitsky } 1853557d2bdcSMaxim Levitsky 1854557d2bdcSMaxim Levitsky slot_count = bitmap_count_one(&slots_to_erase_bitmap, 1855557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1856557d2bdcSMaxim Levitsky if (slot_count == 0) { 1857557d2bdcSMaxim Levitsky error_setg(errp, 1858557d2bdcSMaxim Levitsky "No keyslots match given (old) password for erase operation"); 1859557d2bdcSMaxim Levitsky return -1; 1860557d2bdcSMaxim Levitsky } 1861557d2bdcSMaxim Levitsky 1862557d2bdcSMaxim Levitsky if (!force && 1863557d2bdcSMaxim Levitsky slot_count == qcrypto_block_luks_count_active_slots(luks)) { 1864557d2bdcSMaxim Levitsky error_setg(errp, 1865557d2bdcSMaxim Levitsky "All the active keyslots match the (old) password that " 1866557d2bdcSMaxim Levitsky "was given and erasing them will erase all the data in " 1867557d2bdcSMaxim Levitsky "the image irreversibly - refusing operation"); 1868557d2bdcSMaxim Levitsky return -1; 1869557d2bdcSMaxim Levitsky } 1870557d2bdcSMaxim Levitsky 1871557d2bdcSMaxim Levitsky /* Now apply the update */ 1872557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1873557d2bdcSMaxim Levitsky if (!test_bit(i, &slots_to_erase_bitmap)) { 1874557d2bdcSMaxim Levitsky continue; 1875557d2bdcSMaxim Levitsky } 1876557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, i, writefunc, 1877557d2bdcSMaxim Levitsky opaque, errp)) { 1878557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %zu", i); 1879557d2bdcSMaxim Levitsky return -1; 1880557d2bdcSMaxim Levitsky } 1881557d2bdcSMaxim Levitsky } 1882557d2bdcSMaxim Levitsky } else { 1883557d2bdcSMaxim Levitsky error_setg(errp, 1884557d2bdcSMaxim Levitsky "To erase keyslot(s), either explicit keyslot index " 1885557d2bdcSMaxim Levitsky "or the password currently contained in them must be given"); 1886557d2bdcSMaxim Levitsky return -1; 1887557d2bdcSMaxim Levitsky } 1888557d2bdcSMaxim Levitsky return 0; 1889557d2bdcSMaxim Levitsky } 1890557d2bdcSMaxim Levitsky 1891557d2bdcSMaxim Levitsky static int 1892557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block, 1893557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1894557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1895557d2bdcSMaxim Levitsky void *opaque, 1896557d2bdcSMaxim Levitsky QCryptoBlockAmendOptions *options, 1897557d2bdcSMaxim Levitsky bool force, 1898557d2bdcSMaxim Levitsky Error **errp) 1899557d2bdcSMaxim Levitsky { 1900557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; 1901557d2bdcSMaxim Levitsky 1902557d2bdcSMaxim Levitsky switch (opts_luks->state) { 1903557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: 1904557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_add_keyslot(block, readfunc, 1905557d2bdcSMaxim Levitsky writefunc, opaque, 1906557d2bdcSMaxim Levitsky opts_luks, force, errp); 1907557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: 1908557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, 1909557d2bdcSMaxim Levitsky writefunc, opaque, 1910557d2bdcSMaxim Levitsky opts_luks, force, errp); 1911557d2bdcSMaxim Levitsky default: 1912557d2bdcSMaxim Levitsky g_assert_not_reached(); 1913557d2bdcSMaxim Levitsky } 1914557d2bdcSMaxim Levitsky } 19153e308f20SDaniel P. Berrange 191640c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 191740c85028SDaniel P. Berrange QCryptoBlockInfo *info, 191840c85028SDaniel P. Berrange Error **errp) 191940c85028SDaniel P. Berrange { 192040c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 192140c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 1922c3033fd3SEric Blake QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots; 192340c85028SDaniel P. Berrange size_t i; 192440c85028SDaniel P. Berrange 192540c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 192640c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 192740c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 192840c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 192940c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 193040c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 193140c85028SDaniel P. Berrange } 193240c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 193340c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 193440c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 193540c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 193640c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 193740c85028SDaniel P. Berrange 193840c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1939c3033fd3SEric Blake slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 194040c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 194140c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1942f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 194340c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 194440c85028SDaniel P. Berrange if (slot->active) { 194540c85028SDaniel P. Berrange slot->has_iters = true; 194640c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 194740c85028SDaniel P. Berrange slot->has_stripes = true; 194840c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 194940c85028SDaniel P. Berrange } 195040c85028SDaniel P. Berrange 1951c3033fd3SEric Blake QAPI_LIST_APPEND(tail, slot); 195240c85028SDaniel P. Berrange } 195340c85028SDaniel P. Berrange 195440c85028SDaniel P. Berrange return 0; 195540c85028SDaniel P. Berrange } 195640c85028SDaniel P. Berrange 195740c85028SDaniel P. Berrange 19583e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 19593e308f20SDaniel P. Berrange { 1960557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1961557d2bdcSMaxim Levitsky if (luks) { 1962557d2bdcSMaxim Levitsky g_free(luks->secret); 1963557d2bdcSMaxim Levitsky g_free(luks); 1964557d2bdcSMaxim Levitsky } 19653e308f20SDaniel P. Berrange } 19663e308f20SDaniel P. Berrange 19673e308f20SDaniel P. Berrange 19683e308f20SDaniel P. Berrange static int 19693e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 19704609742aSDaniel P. Berrange uint64_t offset, 19713e308f20SDaniel P. Berrange uint8_t *buf, 19723e308f20SDaniel P. Berrange size_t len, 19733e308f20SDaniel P. Berrange Error **errp) 19743e308f20SDaniel P. Berrange { 19754609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19764609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19770f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 19783e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19794609742aSDaniel P. Berrange offset, buf, len, errp); 19803e308f20SDaniel P. Berrange } 19813e308f20SDaniel P. Berrange 19823e308f20SDaniel P. Berrange 19833e308f20SDaniel P. Berrange static int 19843e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 19854609742aSDaniel P. Berrange uint64_t offset, 19863e308f20SDaniel P. Berrange uint8_t *buf, 19873e308f20SDaniel P. Berrange size_t len, 19883e308f20SDaniel P. Berrange Error **errp) 19893e308f20SDaniel P. Berrange { 19904609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19914609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19920f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 19933e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19944609742aSDaniel P. Berrange offset, buf, len, errp); 19953e308f20SDaniel P. Berrange } 19963e308f20SDaniel P. Berrange 19973e308f20SDaniel P. Berrange 19983e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 19993e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 20003e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 2001557d2bdcSMaxim Levitsky .amend = qcrypto_block_luks_amend_options, 200240c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 20033e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 20043e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 20053e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 20063e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 20073e308f20SDaniel P. Berrange }; 2008