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 93e308f20SDaniel P. Berrange * version 2 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 253e308f20SDaniel P. Berrange #include "crypto/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" 323e308f20SDaniel P. Berrange 333e308f20SDaniel P. Berrange #ifdef CONFIG_UUID 343e308f20SDaniel P. Berrange #include <uuid/uuid.h> 353e308f20SDaniel P. Berrange #endif 363e308f20SDaniel P. Berrange 373e308f20SDaniel P. Berrange #include "qemu/coroutine.h" 383e308f20SDaniel P. Berrange 393e308f20SDaniel P. Berrange /* 403e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is 413e308f20SDaniel P. Berrange * 423e308f20SDaniel P. Berrange * docs/on-disk-format.pdf 433e308f20SDaniel P. Berrange * 443e308f20SDaniel P. Berrange * in 'cryptsetup' package source code 453e308f20SDaniel P. Berrange * 463e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated 473e308f20SDaniel P. Berrange * Oct 16, 2011. 483e308f20SDaniel P. Berrange */ 493e308f20SDaniel P. Berrange 503e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS; 513e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSHeader QCryptoBlockLUKSHeader; 523e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot; 533e308f20SDaniel P. Berrange 543e308f20SDaniel P. Berrange 553e308f20SDaniel P. Berrange /* The following constants are all defined by the LUKS spec */ 563e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_VERSION 1 573e308f20SDaniel P. Berrange 583e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MAGIC_LEN 6 593e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN 32 603e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN 32 613e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN 32 623e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_DIGEST_LEN 20 633e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SALT_LEN 32 643e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_UUID_LEN 40 653e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS 8 663e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_STRIPES 4000 673e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS 1000 683e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS 1000 693e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET 4096 703e308f20SDaniel P. Berrange 713e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED 0x0000DEAD 723e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3 733e308f20SDaniel P. Berrange 743e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL 753e308f20SDaniel P. Berrange 763e308f20SDaniel P. Berrange static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = { 773e308f20SDaniel P. Berrange 'L', 'U', 'K', 'S', 0xBA, 0xBE 783e308f20SDaniel P. Berrange }; 793e308f20SDaniel P. Berrange 803e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap; 813e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap { 823e308f20SDaniel P. Berrange const char *name; 833e308f20SDaniel P. Berrange int id; 843e308f20SDaniel P. Berrange }; 853e308f20SDaniel P. Berrange 863e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap; 873e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap { 883e308f20SDaniel P. Berrange uint32_t key_bytes; 893e308f20SDaniel P. Berrange int id; 903e308f20SDaniel P. Berrange }; 913e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap; 923e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap { 933e308f20SDaniel P. Berrange const char *name; 943e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes; 953e308f20SDaniel P. Berrange }; 963e308f20SDaniel P. Berrange 973e308f20SDaniel P. Berrange 983e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 993e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = { 1003e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 }, 1013e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 }, 1023e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 }, 1033e308f20SDaniel P. Berrange { 0, 0 }, 1043e308f20SDaniel P. Berrange }; 1053e308f20SDaniel P. Berrange 1063e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1073e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = { 1083e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 }, 1093e308f20SDaniel P. Berrange { 0, 0 }, 1103e308f20SDaniel P. Berrange }; 1113e308f20SDaniel P. Berrange 1123e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1133e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = { 1143e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 }, 1153e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 }, 1163e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 }, 1173e308f20SDaniel P. Berrange { 0, 0 }, 1183e308f20SDaniel P. Berrange }; 1193e308f20SDaniel P. Berrange 1203e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1213e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = { 1223e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 }, 1233e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 }, 1243e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 }, 1253e308f20SDaniel P. Berrange { 0, 0 }, 1263e308f20SDaniel P. Berrange }; 1273e308f20SDaniel P. Berrange 1283e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap 1293e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = { 1303e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes }, 1313e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, 1323e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, 1333e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, 1343e308f20SDaniel P. Berrange }; 1353e308f20SDaniel P. Berrange 1363e308f20SDaniel P. Berrange 1373e308f20SDaniel P. Berrange /* 1383e308f20SDaniel P. Berrange * This struct is written to disk in big-endian format, 1393e308f20SDaniel P. Berrange * but operated upon in native-endian format. 1403e308f20SDaniel P. Berrange */ 1413e308f20SDaniel P. Berrange struct QCryptoBlockLUKSKeySlot { 1423e308f20SDaniel P. Berrange /* state of keyslot, enabled/disable */ 1433e308f20SDaniel P. Berrange uint32_t active; 1443e308f20SDaniel P. Berrange /* iterations for PBKDF2 */ 1453e308f20SDaniel P. Berrange uint32_t iterations; 1463e308f20SDaniel P. Berrange /* salt for PBKDF2 */ 1473e308f20SDaniel P. Berrange uint8_t salt[QCRYPTO_BLOCK_LUKS_SALT_LEN]; 1483e308f20SDaniel P. Berrange /* start sector of key material */ 1493e308f20SDaniel P. Berrange uint32_t key_offset; 1503e308f20SDaniel P. Berrange /* number of anti-forensic stripes */ 1513e308f20SDaniel P. Berrange uint32_t stripes; 1523e308f20SDaniel P. Berrange } QEMU_PACKED; 1533e308f20SDaniel P. Berrange 1543e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); 1553e308f20SDaniel P. Berrange 1563e308f20SDaniel P. Berrange 1573e308f20SDaniel P. Berrange /* 1583e308f20SDaniel P. Berrange * This struct is written to disk in big-endian format, 1593e308f20SDaniel P. Berrange * but operated upon in native-endian format. 1603e308f20SDaniel P. Berrange */ 1613e308f20SDaniel P. Berrange struct QCryptoBlockLUKSHeader { 1623e308f20SDaniel P. Berrange /* 'L', 'U', 'K', 'S', '0xBA', '0xBE' */ 1633e308f20SDaniel P. Berrange char magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN]; 1643e308f20SDaniel P. Berrange 1653e308f20SDaniel P. Berrange /* LUKS version, currently 1 */ 1663e308f20SDaniel P. Berrange uint16_t version; 1673e308f20SDaniel P. Berrange 1683e308f20SDaniel P. Berrange /* cipher name specification (aes, etc) */ 1693e308f20SDaniel P. Berrange char cipher_name[QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN]; 1703e308f20SDaniel P. Berrange 1713e308f20SDaniel P. Berrange /* cipher mode specification (cbc-plain, xts-essiv:sha256, etc) */ 1723e308f20SDaniel P. Berrange char cipher_mode[QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN]; 1733e308f20SDaniel P. Berrange 1743e308f20SDaniel P. Berrange /* hash specification (sha256, etc) */ 1753e308f20SDaniel P. Berrange char hash_spec[QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN]; 1763e308f20SDaniel P. Berrange 1773e308f20SDaniel P. Berrange /* start offset of the volume data (in 512 byte sectors) */ 1783e308f20SDaniel P. Berrange uint32_t payload_offset; 1793e308f20SDaniel P. Berrange 1803e308f20SDaniel P. Berrange /* Number of key bytes */ 1813e308f20SDaniel P. Berrange uint32_t key_bytes; 1823e308f20SDaniel P. Berrange 1833e308f20SDaniel P. Berrange /* master key checksum after PBKDF2 */ 1843e308f20SDaniel P. Berrange uint8_t master_key_digest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 1853e308f20SDaniel P. Berrange 1863e308f20SDaniel P. Berrange /* salt for master key PBKDF2 */ 1873e308f20SDaniel P. Berrange uint8_t master_key_salt[QCRYPTO_BLOCK_LUKS_SALT_LEN]; 1883e308f20SDaniel P. Berrange 1893e308f20SDaniel P. Berrange /* iterations for master key PBKDF2 */ 1903e308f20SDaniel P. Berrange uint32_t master_key_iterations; 1913e308f20SDaniel P. Berrange 1923e308f20SDaniel P. Berrange /* UUID of the partition in standard ASCII representation */ 1933e308f20SDaniel P. Berrange uint8_t uuid[QCRYPTO_BLOCK_LUKS_UUID_LEN]; 1943e308f20SDaniel P. Berrange 1953e308f20SDaniel P. Berrange /* key slots */ 1963e308f20SDaniel P. Berrange QCryptoBlockLUKSKeySlot key_slots[QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS]; 1973e308f20SDaniel P. Berrange } QEMU_PACKED; 1983e308f20SDaniel P. Berrange 1993e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592); 2003e308f20SDaniel P. Berrange 2013e308f20SDaniel P. Berrange 2023e308f20SDaniel P. Berrange struct QCryptoBlockLUKS { 2033e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header; 204*40c85028SDaniel P. Berrange 205*40c85028SDaniel P. Berrange /* Cache parsed versions of what's in header fields, 206*40c85028SDaniel P. Berrange * as we can't rely on QCryptoBlock.cipher being 207*40c85028SDaniel P. Berrange * non-NULL */ 208*40c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 209*40c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 210*40c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 211*40c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 212*40c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 2133e308f20SDaniel P. Berrange }; 2143e308f20SDaniel P. Berrange 2153e308f20SDaniel P. Berrange 2163e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name, 2173e308f20SDaniel P. Berrange QCryptoCipherMode mode, 2183e308f20SDaniel P. Berrange uint32_t key_bytes, 2193e308f20SDaniel P. Berrange Error **errp) 2203e308f20SDaniel P. Berrange { 2213e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2223e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2233e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2243e308f20SDaniel P. Berrange size_t i, j; 2253e308f20SDaniel P. Berrange 2263e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) { 2273e308f20SDaniel P. Berrange key_bytes /= 2; 2283e308f20SDaniel P. Berrange } 2293e308f20SDaniel P. Berrange 2303e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2313e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) { 2323e308f20SDaniel P. Berrange continue; 2333e308f20SDaniel P. Berrange } 2343e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2353e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) { 2363e308f20SDaniel P. Berrange return map[i].sizes[j].id; 2373e308f20SDaniel P. Berrange } 2383e308f20SDaniel P. Berrange } 2393e308f20SDaniel P. Berrange } 2403e308f20SDaniel P. Berrange 2413e308f20SDaniel P. Berrange error_setg(errp, "Algorithm %s with key size %d bytes not supported", 2423e308f20SDaniel P. Berrange name, key_bytes); 2433e308f20SDaniel P. Berrange return 0; 2443e308f20SDaniel P. Berrange } 2453e308f20SDaniel P. Berrange 2463e308f20SDaniel P. Berrange static const char * 2473e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg, 2483e308f20SDaniel P. Berrange Error **errp) 2493e308f20SDaniel P. Berrange { 2503e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2513e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2523e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2533e308f20SDaniel P. Berrange size_t i, j; 2543e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2553e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2563e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) { 2573e308f20SDaniel P. Berrange return map[i].name; 2583e308f20SDaniel P. Berrange } 2593e308f20SDaniel P. Berrange } 2603e308f20SDaniel P. Berrange } 2613e308f20SDaniel P. Berrange 2623e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported", 2633e308f20SDaniel P. Berrange QCryptoCipherAlgorithm_lookup[alg]); 2643e308f20SDaniel P. Berrange return NULL; 2653e308f20SDaniel P. Berrange } 2663e308f20SDaniel P. Berrange 2673e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can 2683e308f20SDaniel P. Berrange * make that function emit a more friendly error message */ 2693e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name, 2703e308f20SDaniel P. Berrange const char *const *map, 2713e308f20SDaniel P. Berrange size_t maplen, 2723e308f20SDaniel P. Berrange const char *type, 2733e308f20SDaniel P. Berrange Error **errp) 2743e308f20SDaniel P. Berrange { 2753e308f20SDaniel P. Berrange size_t i; 2763e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2773e308f20SDaniel P. Berrange if (g_str_equal(map[i], name)) { 2783e308f20SDaniel P. Berrange return i; 2793e308f20SDaniel P. Berrange } 2803e308f20SDaniel P. Berrange } 2813e308f20SDaniel P. Berrange 2823e308f20SDaniel P. Berrange error_setg(errp, "%s %s not supported", type, name); 2833e308f20SDaniel P. Berrange return 0; 2843e308f20SDaniel P. Berrange } 2853e308f20SDaniel P. Berrange 2863e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \ 2873e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 2883e308f20SDaniel P. Berrange QCryptoCipherMode_lookup, \ 2893e308f20SDaniel P. Berrange QCRYPTO_CIPHER_MODE__MAX, \ 2903e308f20SDaniel P. Berrange "Cipher mode", \ 2913e308f20SDaniel P. Berrange errp) 2923e308f20SDaniel P. Berrange 2933e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \ 2943e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 2953e308f20SDaniel P. Berrange QCryptoHashAlgorithm_lookup, \ 2963e308f20SDaniel P. Berrange QCRYPTO_HASH_ALG__MAX, \ 2973e308f20SDaniel P. Berrange "Hash algorithm", \ 2983e308f20SDaniel P. Berrange errp) 2993e308f20SDaniel P. Berrange 3003e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \ 3013e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 3023e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm_lookup, \ 3033e308f20SDaniel P. Berrange QCRYPTO_IVGEN_ALG__MAX, \ 3043e308f20SDaniel P. Berrange "IV generator", \ 3053e308f20SDaniel P. Berrange errp) 3063e308f20SDaniel P. Berrange 3073e308f20SDaniel P. Berrange 3083e308f20SDaniel P. Berrange static bool 3093e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf, 3103e308f20SDaniel P. Berrange size_t buf_size) 3113e308f20SDaniel P. Berrange { 3123e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf; 3133e308f20SDaniel P. Berrange 3143e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) && 3153e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic, 3163e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 && 3173e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) { 3183e308f20SDaniel P. Berrange return true; 3193e308f20SDaniel P. Berrange } else { 3203e308f20SDaniel P. Berrange return false; 3213e308f20SDaniel P. Berrange } 3223e308f20SDaniel P. Berrange } 3233e308f20SDaniel P. Berrange 3243e308f20SDaniel P. Berrange 3253e308f20SDaniel P. Berrange /** 3263e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV. 3273e308f20SDaniel P. Berrange * 3283e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV 3293e308f20SDaniel P. Berrange * may be different from the cipher length used for the block 3303e308f20SDaniel P. Berrange * encryption, becauses dm-crypt uses the hash digest length 3313e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher 3323e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as 3333e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest 3343e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined 3353e308f20SDaniel P. Berrange */ 3363e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm 3373e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher, 3383e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 3393e308f20SDaniel P. Berrange Error **errp) 3403e308f20SDaniel P. Berrange { 3413e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 3423e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher); 3433e308f20SDaniel P. Berrange if (digestlen == keylen) { 3443e308f20SDaniel P. Berrange return cipher; 3453e308f20SDaniel P. Berrange } 3463e308f20SDaniel P. Berrange 3473e308f20SDaniel P. Berrange switch (cipher) { 3483e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128: 3493e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192: 3503e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256: 3513e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3523e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) { 3533e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128; 3543e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3553e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) { 3563e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192; 3573e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3583e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) { 3593e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256; 3603e308f20SDaniel P. Berrange } else { 3613e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available", 3623e308f20SDaniel P. Berrange digestlen); 3633e308f20SDaniel P. Berrange return 0; 3643e308f20SDaniel P. Berrange } 3653e308f20SDaniel P. Berrange break; 3663e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128: 3673e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192: 3683e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256: 3693e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3703e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) { 3713e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128; 3723e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3733e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) { 3743e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192; 3753e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3763e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) { 3773e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256; 3783e308f20SDaniel P. Berrange } else { 3793e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available", 3803e308f20SDaniel P. Berrange digestlen); 3813e308f20SDaniel P. Berrange return 0; 3823e308f20SDaniel P. Berrange } 3833e308f20SDaniel P. Berrange break; 3843e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128: 3853e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192: 3863e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256: 3873e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3883e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) { 3893e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128; 3903e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3913e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) { 3923e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192; 3933e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3943e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) { 3953e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256; 3963e308f20SDaniel P. Berrange } else { 3973e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available", 3983e308f20SDaniel P. Berrange digestlen); 3993e308f20SDaniel P. Berrange return 0; 4003e308f20SDaniel P. Berrange } 4013e308f20SDaniel P. Berrange break; 4023e308f20SDaniel P. Berrange default: 4033e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv", 4043e308f20SDaniel P. Berrange QCryptoCipherAlgorithm_lookup[cipher]); 4053e308f20SDaniel P. Berrange return 0; 4063e308f20SDaniel P. Berrange } 4073e308f20SDaniel P. Berrange } 4083e308f20SDaniel P. Berrange 4093e308f20SDaniel P. Berrange /* 4103e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 4113e308f20SDaniel P. Berrange * the master encryption key from the key slot. 4123e308f20SDaniel P. Berrange * 4133e308f20SDaniel P. Berrange * Returns: 4143e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 4153e308f20SDaniel P. Berrange * with the provided password 4163e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 4173e308f20SDaniel P. Berrange * with the provided password 4183e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 4193e308f20SDaniel P. Berrange */ 4203e308f20SDaniel P. Berrange static int 4213e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 4223e308f20SDaniel P. Berrange QCryptoBlockLUKSKeySlot *slot, 4233e308f20SDaniel P. Berrange const char *password, 4243e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg, 4253e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode, 4263e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 4273e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg, 4283e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg, 4293e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash, 4303e308f20SDaniel P. Berrange uint8_t *masterkey, 4313e308f20SDaniel P. Berrange size_t masterkeylen, 4323e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 4333e308f20SDaniel P. Berrange void *opaque, 4343e308f20SDaniel P. Berrange Error **errp) 4353e308f20SDaniel P. Berrange { 4363e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 4373e308f20SDaniel P. Berrange uint8_t *splitkey; 4383e308f20SDaniel P. Berrange size_t splitkeylen; 4393e308f20SDaniel P. Berrange uint8_t *possiblekey; 4403e308f20SDaniel P. Berrange int ret = -1; 4413e308f20SDaniel P. Berrange ssize_t rv; 4423e308f20SDaniel P. Berrange QCryptoCipher *cipher = NULL; 4433e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 4443e308f20SDaniel P. Berrange QCryptoIVGen *ivgen = NULL; 4453e308f20SDaniel P. Berrange size_t niv; 4463e308f20SDaniel P. Berrange 4473e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 4483e308f20SDaniel P. Berrange return 0; 4493e308f20SDaniel P. Berrange } 4503e308f20SDaniel P. Berrange 4513e308f20SDaniel P. Berrange splitkeylen = masterkeylen * slot->stripes; 4523e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 4533e308f20SDaniel P. Berrange possiblekey = g_new0(uint8_t, masterkeylen); 4543e308f20SDaniel P. Berrange 4553e308f20SDaniel P. Berrange /* 4563e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 4573e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 4583e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 4593e308f20SDaniel P. Berrange * the key is correct and validate the results of 4603e308f20SDaniel P. Berrange * decryption later. 4613e308f20SDaniel P. Berrange */ 4623e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(hash, 4633e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 4643e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 4653e308f20SDaniel P. Berrange slot->iterations, 4663e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4673e308f20SDaniel P. Berrange errp) < 0) { 4683e308f20SDaniel P. Berrange goto cleanup; 4693e308f20SDaniel P. Berrange } 4703e308f20SDaniel P. Berrange 4713e308f20SDaniel P. Berrange /* 4723e308f20SDaniel P. Berrange * We need to read the master key material from the 4733e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 4743e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 4753e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 4763e308f20SDaniel P. Berrange * then encrypted. 4773e308f20SDaniel P. Berrange */ 4783e308f20SDaniel P. Berrange rv = readfunc(block, 4793e308f20SDaniel P. Berrange slot->key_offset * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 4803e308f20SDaniel P. Berrange splitkey, splitkeylen, 4813e308f20SDaniel P. Berrange errp, 4823e308f20SDaniel P. Berrange opaque); 4833e308f20SDaniel P. Berrange if (rv < 0) { 4843e308f20SDaniel P. Berrange goto cleanup; 4853e308f20SDaniel P. Berrange } 4863e308f20SDaniel P. Berrange 4873e308f20SDaniel P. Berrange 4883e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 4893e308f20SDaniel P. Berrange * the split master key material */ 4903e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(cipheralg, ciphermode, 4913e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4923e308f20SDaniel P. Berrange errp); 4933e308f20SDaniel P. Berrange if (!cipher) { 4943e308f20SDaniel P. Berrange goto cleanup; 4953e308f20SDaniel P. Berrange } 4963e308f20SDaniel P. Berrange 4973e308f20SDaniel P. Berrange niv = qcrypto_cipher_get_iv_len(cipheralg, 4983e308f20SDaniel P. Berrange ciphermode); 4993e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(ivalg, 5003e308f20SDaniel P. Berrange ivcipheralg, 5013e308f20SDaniel P. Berrange ivhash, 5023e308f20SDaniel P. Berrange possiblekey, masterkeylen, 5033e308f20SDaniel P. Berrange errp); 5043e308f20SDaniel P. Berrange if (!ivgen) { 5053e308f20SDaniel P. Berrange goto cleanup; 5063e308f20SDaniel P. Berrange } 5073e308f20SDaniel P. Berrange 5083e308f20SDaniel P. Berrange 5093e308f20SDaniel P. Berrange /* 5103e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 5113e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 5123e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 5133e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 5143e308f20SDaniel P. Berrange * key crosses a sector boundary. 5153e308f20SDaniel P. Berrange */ 5163e308f20SDaniel P. Berrange if (qcrypto_block_decrypt_helper(cipher, 5173e308f20SDaniel P. Berrange niv, 5183e308f20SDaniel P. Berrange ivgen, 5193e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 5203e308f20SDaniel P. Berrange 0, 5213e308f20SDaniel P. Berrange splitkey, 5223e308f20SDaniel P. Berrange splitkeylen, 5233e308f20SDaniel P. Berrange errp) < 0) { 5243e308f20SDaniel P. Berrange goto cleanup; 5253e308f20SDaniel P. Berrange } 5263e308f20SDaniel P. Berrange 5273e308f20SDaniel P. Berrange /* 5283e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 5293e308f20SDaniel P. Berrange * it back together to get the actual master key. 5303e308f20SDaniel P. Berrange */ 5313e308f20SDaniel P. Berrange if (qcrypto_afsplit_decode(hash, 5323e308f20SDaniel P. Berrange masterkeylen, 5333e308f20SDaniel P. Berrange slot->stripes, 5343e308f20SDaniel P. Berrange splitkey, 5353e308f20SDaniel P. Berrange masterkey, 5363e308f20SDaniel P. Berrange errp) < 0) { 5373e308f20SDaniel P. Berrange goto cleanup; 5383e308f20SDaniel P. Berrange } 5393e308f20SDaniel P. Berrange 5403e308f20SDaniel P. Berrange 5413e308f20SDaniel P. Berrange /* 5423e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 5433e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 5443e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 5453e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 5463e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 5473e308f20SDaniel P. Berrange * header 5483e308f20SDaniel P. Berrange */ 5493e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(hash, 5503e308f20SDaniel P. Berrange masterkey, masterkeylen, 5513e308f20SDaniel P. Berrange luks->header.master_key_salt, 5523e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 5533e308f20SDaniel P. Berrange luks->header.master_key_iterations, 5543e308f20SDaniel P. Berrange keydigest, G_N_ELEMENTS(keydigest), 5553e308f20SDaniel P. Berrange errp) < 0) { 5563e308f20SDaniel P. Berrange goto cleanup; 5573e308f20SDaniel P. Berrange } 5583e308f20SDaniel P. Berrange 5593e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 5603e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 5613e308f20SDaniel P. Berrange /* Success, we got the right master key */ 5623e308f20SDaniel P. Berrange ret = 1; 5633e308f20SDaniel P. Berrange goto cleanup; 5643e308f20SDaniel P. Berrange } 5653e308f20SDaniel P. Berrange 5663e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 5673e308f20SDaniel P. Berrange * tell caller to try another slot */ 5683e308f20SDaniel P. Berrange ret = 0; 5693e308f20SDaniel P. Berrange 5703e308f20SDaniel P. Berrange cleanup: 5713e308f20SDaniel P. Berrange qcrypto_ivgen_free(ivgen); 5723e308f20SDaniel P. Berrange qcrypto_cipher_free(cipher); 5733e308f20SDaniel P. Berrange g_free(splitkey); 5743e308f20SDaniel P. Berrange g_free(possiblekey); 5753e308f20SDaniel P. Berrange return ret; 5763e308f20SDaniel P. Berrange } 5773e308f20SDaniel P. Berrange 5783e308f20SDaniel P. Berrange 5793e308f20SDaniel P. Berrange /* 5803e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 5813e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 5823e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 5833e308f20SDaniel P. Berrange * 5843e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 5853e308f20SDaniel P. Berrange */ 5863e308f20SDaniel P. Berrange static int 5873e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 5883e308f20SDaniel P. Berrange const char *password, 5893e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg, 5903e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode, 5913e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 5923e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg, 5933e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg, 5943e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash, 5953e308f20SDaniel P. Berrange uint8_t **masterkey, 5963e308f20SDaniel P. Berrange size_t *masterkeylen, 5973e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 5983e308f20SDaniel P. Berrange void *opaque, 5993e308f20SDaniel P. Berrange Error **errp) 6003e308f20SDaniel P. Berrange { 6013e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 6023e308f20SDaniel P. Berrange size_t i; 6033e308f20SDaniel P. Berrange int rv; 6043e308f20SDaniel P. Berrange 6053e308f20SDaniel P. Berrange *masterkey = g_new0(uint8_t, luks->header.key_bytes); 6063e308f20SDaniel P. Berrange *masterkeylen = luks->header.key_bytes; 6073e308f20SDaniel P. Berrange 6083e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 6093e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 6103e308f20SDaniel P. Berrange &luks->header.key_slots[i], 6113e308f20SDaniel P. Berrange password, 6123e308f20SDaniel P. Berrange cipheralg, 6133e308f20SDaniel P. Berrange ciphermode, 6143e308f20SDaniel P. Berrange hash, 6153e308f20SDaniel P. Berrange ivalg, 6163e308f20SDaniel P. Berrange ivcipheralg, 6173e308f20SDaniel P. Berrange ivhash, 6183e308f20SDaniel P. Berrange *masterkey, 6193e308f20SDaniel P. Berrange *masterkeylen, 6203e308f20SDaniel P. Berrange readfunc, 6213e308f20SDaniel P. Berrange opaque, 6223e308f20SDaniel P. Berrange errp); 6233e308f20SDaniel P. Berrange if (rv < 0) { 6243e308f20SDaniel P. Berrange goto error; 6253e308f20SDaniel P. Berrange } 6263e308f20SDaniel P. Berrange if (rv == 1) { 6273e308f20SDaniel P. Berrange return 0; 6283e308f20SDaniel P. Berrange } 6293e308f20SDaniel P. Berrange } 6303e308f20SDaniel P. Berrange 6313e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 6323e308f20SDaniel P. Berrange 6333e308f20SDaniel P. Berrange error: 6343e308f20SDaniel P. Berrange g_free(*masterkey); 6353e308f20SDaniel P. Berrange *masterkey = NULL; 6363e308f20SDaniel P. Berrange *masterkeylen = 0; 6373e308f20SDaniel P. Berrange return -1; 6383e308f20SDaniel P. Berrange } 6393e308f20SDaniel P. Berrange 6403e308f20SDaniel P. Berrange 6413e308f20SDaniel P. Berrange static int 6423e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 6433e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 6443e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 6453e308f20SDaniel P. Berrange void *opaque, 6463e308f20SDaniel P. Berrange unsigned int flags, 6473e308f20SDaniel P. Berrange Error **errp) 6483e308f20SDaniel P. Berrange { 6493e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 6503e308f20SDaniel P. Berrange Error *local_err = NULL; 6513e308f20SDaniel P. Berrange int ret = 0; 6523e308f20SDaniel P. Berrange size_t i; 6533e308f20SDaniel P. Berrange ssize_t rv; 6543e308f20SDaniel P. Berrange uint8_t *masterkey = NULL; 6553e308f20SDaniel P. Berrange size_t masterkeylen; 6563e308f20SDaniel P. Berrange char *ivgen_name, *ivhash_name; 6573e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode; 6583e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg; 6593e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg; 6603e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg; 6613e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash; 6623e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash; 6633e308f20SDaniel P. Berrange char *password = NULL; 6643e308f20SDaniel P. Berrange 6653e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 6663e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 6673e308f20SDaniel P. Berrange error_setg(errp, "Parameter 'key-secret' is required for cipher"); 6683e308f20SDaniel P. Berrange return -1; 6693e308f20SDaniel P. Berrange } 6703e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 6713e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 6723e308f20SDaniel P. Berrange if (!password) { 6733e308f20SDaniel P. Berrange return -1; 6743e308f20SDaniel P. Berrange } 6753e308f20SDaniel P. Berrange } 6763e308f20SDaniel P. Berrange 6773e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 6783e308f20SDaniel P. Berrange block->opaque = luks; 6793e308f20SDaniel P. Berrange 6803e308f20SDaniel P. Berrange /* Read the entire LUKS header, minus the key material from 6813e308f20SDaniel P. Berrange * the underlying device */ 6823e308f20SDaniel P. Berrange rv = readfunc(block, 0, 6833e308f20SDaniel P. Berrange (uint8_t *)&luks->header, 6843e308f20SDaniel P. Berrange sizeof(luks->header), 6853e308f20SDaniel P. Berrange errp, 6863e308f20SDaniel P. Berrange opaque); 6873e308f20SDaniel P. Berrange if (rv < 0) { 6883e308f20SDaniel P. Berrange ret = rv; 6893e308f20SDaniel P. Berrange goto fail; 6903e308f20SDaniel P. Berrange } 6913e308f20SDaniel P. Berrange 6923e308f20SDaniel P. Berrange /* The header is always stored in big-endian format, so 6933e308f20SDaniel P. Berrange * convert everything to native */ 6943e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 6953e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.payload_offset); 6963e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_bytes); 6973e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 6983e308f20SDaniel P. Berrange 6993e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 7003e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 7013e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 7023e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].key_offset); 7033e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 7043e308f20SDaniel P. Berrange } 7053e308f20SDaniel P. Berrange 7063e308f20SDaniel P. Berrange if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 7073e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 7083e308f20SDaniel P. Berrange error_setg(errp, "Volume is not in LUKS format"); 7093e308f20SDaniel P. Berrange ret = -EINVAL; 7103e308f20SDaniel P. Berrange goto fail; 7113e308f20SDaniel P. Berrange } 7123e308f20SDaniel P. Berrange if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 7133e308f20SDaniel P. Berrange error_setg(errp, "LUKS version %" PRIu32 " is not supported", 7143e308f20SDaniel P. Berrange luks->header.version); 7153e308f20SDaniel P. Berrange ret = -ENOTSUP; 7163e308f20SDaniel P. Berrange goto fail; 7173e308f20SDaniel P. Berrange } 7183e308f20SDaniel P. Berrange 7193e308f20SDaniel P. Berrange /* 7203e308f20SDaniel P. Berrange * The cipher_mode header contains a string that we have 7213e308f20SDaniel P. Berrange * to further parse, of the format 7223e308f20SDaniel P. Berrange * 7233e308f20SDaniel P. Berrange * <cipher-mode>-<iv-generator>[:<iv-hash>] 7243e308f20SDaniel P. Berrange * 7253e308f20SDaniel P. Berrange * eg cbc-essiv:sha256, cbc-plain64 7263e308f20SDaniel P. Berrange */ 7273e308f20SDaniel P. Berrange ivgen_name = strchr(luks->header.cipher_mode, '-'); 7283e308f20SDaniel P. Berrange if (!ivgen_name) { 7293e308f20SDaniel P. Berrange ret = -EINVAL; 7303e308f20SDaniel P. Berrange error_setg(errp, "Unexpected cipher mode string format %s", 7313e308f20SDaniel P. Berrange luks->header.cipher_mode); 7323e308f20SDaniel P. Berrange goto fail; 7333e308f20SDaniel P. Berrange } 7343e308f20SDaniel P. Berrange *ivgen_name = '\0'; 7353e308f20SDaniel P. Berrange ivgen_name++; 7363e308f20SDaniel P. Berrange 7373e308f20SDaniel P. Berrange ivhash_name = strchr(ivgen_name, ':'); 7383e308f20SDaniel P. Berrange if (!ivhash_name) { 7393e308f20SDaniel P. Berrange ivhash = 0; 7403e308f20SDaniel P. Berrange } else { 7413e308f20SDaniel P. Berrange *ivhash_name = '\0'; 7423e308f20SDaniel P. Berrange ivhash_name++; 7433e308f20SDaniel P. Berrange 7443e308f20SDaniel P. Berrange ivhash = qcrypto_block_luks_hash_name_lookup(ivhash_name, 7453e308f20SDaniel P. Berrange &local_err); 7463e308f20SDaniel P. Berrange if (local_err) { 7473e308f20SDaniel P. Berrange ret = -ENOTSUP; 7483e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7493e308f20SDaniel P. Berrange goto fail; 7503e308f20SDaniel P. Berrange } 7513e308f20SDaniel P. Berrange } 7523e308f20SDaniel P. Berrange 7533e308f20SDaniel P. Berrange ciphermode = qcrypto_block_luks_cipher_mode_lookup(luks->header.cipher_mode, 7543e308f20SDaniel P. Berrange &local_err); 7553e308f20SDaniel P. Berrange if (local_err) { 7563e308f20SDaniel P. Berrange ret = -ENOTSUP; 7573e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7583e308f20SDaniel P. Berrange goto fail; 7593e308f20SDaniel P. Berrange } 7603e308f20SDaniel P. Berrange 7613e308f20SDaniel P. Berrange cipheralg = qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 7623e308f20SDaniel P. Berrange ciphermode, 7633e308f20SDaniel P. Berrange luks->header.key_bytes, 7643e308f20SDaniel P. Berrange &local_err); 7653e308f20SDaniel P. Berrange if (local_err) { 7663e308f20SDaniel P. Berrange ret = -ENOTSUP; 7673e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7683e308f20SDaniel P. Berrange goto fail; 7693e308f20SDaniel P. Berrange } 7703e308f20SDaniel P. Berrange 7713e308f20SDaniel P. Berrange hash = qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 7723e308f20SDaniel P. Berrange &local_err); 7733e308f20SDaniel P. Berrange if (local_err) { 7743e308f20SDaniel P. Berrange ret = -ENOTSUP; 7753e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7763e308f20SDaniel P. Berrange goto fail; 7773e308f20SDaniel P. Berrange } 7783e308f20SDaniel P. Berrange 7793e308f20SDaniel P. Berrange ivalg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 7803e308f20SDaniel P. Berrange &local_err); 7813e308f20SDaniel P. Berrange if (local_err) { 7823e308f20SDaniel P. Berrange ret = -ENOTSUP; 7833e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7843e308f20SDaniel P. Berrange goto fail; 7853e308f20SDaniel P. Berrange } 7863e308f20SDaniel P. Berrange 7873e308f20SDaniel P. Berrange if (ivalg == QCRYPTO_IVGEN_ALG_ESSIV) { 7888b7cdba3SDaniel P. Berrange if (!ivhash_name) { 7898b7cdba3SDaniel P. Berrange ret = -EINVAL; 7908b7cdba3SDaniel P. Berrange error_setg(errp, "Missing IV generator hash specification"); 7918b7cdba3SDaniel P. Berrange goto fail; 7928b7cdba3SDaniel P. Berrange } 7933e308f20SDaniel P. Berrange ivcipheralg = qcrypto_block_luks_essiv_cipher(cipheralg, 7943e308f20SDaniel P. Berrange ivhash, 7953e308f20SDaniel P. Berrange &local_err); 7963e308f20SDaniel P. Berrange if (local_err) { 7973e308f20SDaniel P. Berrange ret = -ENOTSUP; 7983e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7993e308f20SDaniel P. Berrange goto fail; 8003e308f20SDaniel P. Berrange } 8013e308f20SDaniel P. Berrange } else { 8028b7cdba3SDaniel P. Berrange /* Note we parsed the ivhash_name earlier in the cipher_mode 8038b7cdba3SDaniel P. Berrange * spec string even with plain/plain64 ivgens, but we 8048b7cdba3SDaniel P. Berrange * will ignore it, since it is irrelevant for these ivgens. 8058b7cdba3SDaniel P. Berrange * This is for compat with dm-crypt which will silently 8068b7cdba3SDaniel P. Berrange * ignore hash names with these ivgens rather than report 8078b7cdba3SDaniel P. Berrange * an error about the invalid usage 8088b7cdba3SDaniel P. Berrange */ 8093e308f20SDaniel P. Berrange ivcipheralg = cipheralg; 8103e308f20SDaniel P. Berrange } 8113e308f20SDaniel P. Berrange 8123e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 8133e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 8143e308f20SDaniel P. Berrange * and unlock the master key from that slot. 8153e308f20SDaniel P. Berrange */ 8163e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 8173e308f20SDaniel P. Berrange password, 8183e308f20SDaniel P. Berrange cipheralg, ciphermode, 8193e308f20SDaniel P. Berrange hash, 8203e308f20SDaniel P. Berrange ivalg, 8213e308f20SDaniel P. Berrange ivcipheralg, 8223e308f20SDaniel P. Berrange ivhash, 8233e308f20SDaniel P. Berrange &masterkey, &masterkeylen, 8243e308f20SDaniel P. Berrange readfunc, opaque, 8253e308f20SDaniel P. Berrange errp) < 0) { 8263e308f20SDaniel P. Berrange ret = -EACCES; 8273e308f20SDaniel P. Berrange goto fail; 8283e308f20SDaniel P. Berrange } 8293e308f20SDaniel P. Berrange 8303e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 8313e308f20SDaniel P. Berrange * block device payload decryption objects 8323e308f20SDaniel P. Berrange */ 8333e308f20SDaniel P. Berrange block->kdfhash = hash; 8343e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(cipheralg, 8353e308f20SDaniel P. Berrange ciphermode); 8363e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(ivalg, 8373e308f20SDaniel P. Berrange ivcipheralg, 8383e308f20SDaniel P. Berrange ivhash, 8393e308f20SDaniel P. Berrange masterkey, masterkeylen, 8403e308f20SDaniel P. Berrange errp); 8413e308f20SDaniel P. Berrange if (!block->ivgen) { 8423e308f20SDaniel P. Berrange ret = -ENOTSUP; 8433e308f20SDaniel P. Berrange goto fail; 8443e308f20SDaniel P. Berrange } 8453e308f20SDaniel P. Berrange 8463e308f20SDaniel P. Berrange block->cipher = qcrypto_cipher_new(cipheralg, 8473e308f20SDaniel P. Berrange ciphermode, 8483e308f20SDaniel P. Berrange masterkey, masterkeylen, 8493e308f20SDaniel P. Berrange errp); 8503e308f20SDaniel P. Berrange if (!block->cipher) { 8513e308f20SDaniel P. Berrange ret = -ENOTSUP; 8523e308f20SDaniel P. Berrange goto fail; 8533e308f20SDaniel P. Berrange } 8543e308f20SDaniel P. Berrange } 8553e308f20SDaniel P. Berrange 8563e308f20SDaniel P. Berrange block->payload_offset = luks->header.payload_offset * 8573e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 8583e308f20SDaniel P. Berrange 859*40c85028SDaniel P. Berrange luks->cipher_alg = cipheralg; 860*40c85028SDaniel P. Berrange luks->cipher_mode = ciphermode; 861*40c85028SDaniel P. Berrange luks->ivgen_alg = ivalg; 862*40c85028SDaniel P. Berrange luks->ivgen_hash_alg = ivhash; 863*40c85028SDaniel P. Berrange luks->hash_alg = hash; 864*40c85028SDaniel P. Berrange 8653e308f20SDaniel P. Berrange g_free(masterkey); 8663e308f20SDaniel P. Berrange g_free(password); 8673e308f20SDaniel P. Berrange 8683e308f20SDaniel P. Berrange return 0; 8693e308f20SDaniel P. Berrange 8703e308f20SDaniel P. Berrange fail: 8713e308f20SDaniel P. Berrange g_free(masterkey); 8723e308f20SDaniel P. Berrange qcrypto_cipher_free(block->cipher); 8733e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 8743e308f20SDaniel P. Berrange g_free(luks); 8753e308f20SDaniel P. Berrange g_free(password); 8763e308f20SDaniel P. Berrange return ret; 8773e308f20SDaniel P. Berrange } 8783e308f20SDaniel P. Berrange 8793e308f20SDaniel P. Berrange 8803e308f20SDaniel P. Berrange static int 8813e308f20SDaniel P. Berrange qcrypto_block_luks_uuid_gen(uint8_t *uuidstr, Error **errp) 8823e308f20SDaniel P. Berrange { 8833e308f20SDaniel P. Berrange #ifdef CONFIG_UUID 8843e308f20SDaniel P. Berrange uuid_t uuid; 8853e308f20SDaniel P. Berrange uuid_generate(uuid); 8863e308f20SDaniel P. Berrange uuid_unparse(uuid, (char *)uuidstr); 8873e308f20SDaniel P. Berrange return 0; 8883e308f20SDaniel P. Berrange #else 8893e308f20SDaniel P. Berrange error_setg(errp, "Unable to generate uuids on this platform"); 8903e308f20SDaniel P. Berrange return -1; 8913e308f20SDaniel P. Berrange #endif 8923e308f20SDaniel P. Berrange } 8933e308f20SDaniel P. Berrange 8943e308f20SDaniel P. Berrange static int 8953e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 8963e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 8973e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 8983e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 8993e308f20SDaniel P. Berrange void *opaque, 9003e308f20SDaniel P. Berrange Error **errp) 9013e308f20SDaniel P. Berrange { 9023e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 9033e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 9043e308f20SDaniel P. Berrange Error *local_err = NULL; 9053e308f20SDaniel P. Berrange uint8_t *masterkey = NULL; 9063e308f20SDaniel P. Berrange uint8_t *slotkey = NULL; 9073e308f20SDaniel P. Berrange uint8_t *splitkey = NULL; 9083e308f20SDaniel P. Berrange size_t splitkeylen = 0; 9093e308f20SDaniel P. Berrange size_t i; 9103e308f20SDaniel P. Berrange QCryptoCipher *cipher = NULL; 9113e308f20SDaniel P. Berrange QCryptoIVGen *ivgen = NULL; 9123e308f20SDaniel P. Berrange char *password; 9133e308f20SDaniel P. Berrange const char *cipher_alg; 9143e308f20SDaniel P. Berrange const char *cipher_mode; 9153e308f20SDaniel P. Berrange const char *ivgen_alg; 9163e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 9173e308f20SDaniel P. Berrange const char *hash_alg; 9183e308f20SDaniel P. Berrange char *cipher_mode_spec = NULL; 9193e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg = 0; 9203e308f20SDaniel P. Berrange 9213e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 9223e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 9233e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 9243e308f20SDaniel P. Berrange } 9253e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 9263e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 9273e308f20SDaniel P. Berrange } 9283e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 9293e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 9303e308f20SDaniel P. Berrange } 9313e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 9323e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 9333e308f20SDaniel P. Berrange } 9348b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9358b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 9368b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 9378b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 9388b7cdba3SDaniel P. Berrange } 9398b7cdba3SDaniel P. Berrange } 9408b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 9418b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 9428b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 9433e308f20SDaniel P. Berrange 9443e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 9453e308f20SDaniel P. Berrange error_setg(errp, "Parameter 'key-secret' is required for cipher"); 9463e308f20SDaniel P. Berrange return -1; 9473e308f20SDaniel P. Berrange } 9483e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 9493e308f20SDaniel P. Berrange if (!password) { 9503e308f20SDaniel P. Berrange return -1; 9513e308f20SDaniel P. Berrange } 9523e308f20SDaniel P. Berrange 9533e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 9543e308f20SDaniel P. Berrange block->opaque = luks; 9553e308f20SDaniel P. Berrange 9563e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 9573e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 9583e308f20SDaniel P. Berrange 9593e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 9603e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 9613e308f20SDaniel P. Berrange * it out to disk 9623e308f20SDaniel P. Berrange */ 9633e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 9643e308f20SDaniel P. Berrange if (qcrypto_block_luks_uuid_gen(luks->header.uuid, 9653e308f20SDaniel P. Berrange errp) < 0) { 9663e308f20SDaniel P. Berrange goto error; 9673e308f20SDaniel P. Berrange } 9683e308f20SDaniel P. Berrange 9693e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 9703e308f20SDaniel P. Berrange errp); 9713e308f20SDaniel P. Berrange if (!cipher_alg) { 9723e308f20SDaniel P. Berrange goto error; 9733e308f20SDaniel P. Berrange } 9743e308f20SDaniel P. Berrange 9753e308f20SDaniel P. Berrange cipher_mode = QCryptoCipherMode_lookup[luks_opts.cipher_mode]; 9763e308f20SDaniel P. Berrange ivgen_alg = QCryptoIVGenAlgorithm_lookup[luks_opts.ivgen_alg]; 9773e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 9783e308f20SDaniel P. Berrange ivgen_hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.ivgen_hash_alg]; 9793e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 9803e308f20SDaniel P. Berrange ivgen_hash_alg); 9813e308f20SDaniel P. Berrange } else { 9823e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 9833e308f20SDaniel P. Berrange } 9843e308f20SDaniel P. Berrange hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.hash_alg]; 9853e308f20SDaniel P. Berrange 9863e308f20SDaniel P. Berrange 9873e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 9883e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 9893e308f20SDaniel P. Berrange cipher_alg); 9903e308f20SDaniel P. Berrange goto error; 9913e308f20SDaniel P. Berrange } 9923e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 9933e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 9943e308f20SDaniel P. Berrange cipher_mode_spec); 9953e308f20SDaniel P. Berrange goto error; 9963e308f20SDaniel P. Berrange } 9973e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 9983e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 9993e308f20SDaniel P. Berrange hash_alg); 10003e308f20SDaniel P. Berrange goto error; 10013e308f20SDaniel P. Berrange } 10023e308f20SDaniel P. Berrange 10033e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 10043e308f20SDaniel P. Berrange ivcipheralg = qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 10053e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 10063e308f20SDaniel P. Berrange &local_err); 10073e308f20SDaniel P. Berrange if (local_err) { 10083e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10093e308f20SDaniel P. Berrange goto error; 10103e308f20SDaniel P. Berrange } 10113e308f20SDaniel P. Berrange } else { 10123e308f20SDaniel P. Berrange ivcipheralg = luks_opts.cipher_alg; 10133e308f20SDaniel P. Berrange } 10143e308f20SDaniel P. Berrange 10153e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 10163e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 10173e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 10183e308f20SDaniel P. Berrange 10193e308f20SDaniel P. Berrange luks->header.key_bytes = qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 10203e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 10213e308f20SDaniel P. Berrange luks->header.key_bytes *= 2; 10223e308f20SDaniel P. Berrange } 10233e308f20SDaniel P. Berrange 10243e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 10253e308f20SDaniel P. Berrange * with PBKDF later 10263e308f20SDaniel P. Berrange */ 10273e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 10283e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10293e308f20SDaniel P. Berrange errp) < 0) { 10303e308f20SDaniel P. Berrange goto error; 10313e308f20SDaniel P. Berrange } 10323e308f20SDaniel P. Berrange 10333e308f20SDaniel P. Berrange /* Generate random master key */ 10343e308f20SDaniel P. Berrange masterkey = g_new0(uint8_t, luks->header.key_bytes); 10353e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 10363e308f20SDaniel P. Berrange luks->header.key_bytes, errp) < 0) { 10373e308f20SDaniel P. Berrange goto error; 10383e308f20SDaniel P. Berrange } 10393e308f20SDaniel P. Berrange 10403e308f20SDaniel P. Berrange 10413e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 10423e308f20SDaniel P. Berrange block->cipher = qcrypto_cipher_new(luks_opts.cipher_alg, 10433e308f20SDaniel P. Berrange luks_opts.cipher_mode, 10443e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10453e308f20SDaniel P. Berrange errp); 10463e308f20SDaniel P. Berrange if (!block->cipher) { 10473e308f20SDaniel P. Berrange goto error; 10483e308f20SDaniel P. Berrange } 10493e308f20SDaniel P. Berrange 10503e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 10513e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 10523e308f20SDaniel P. Berrange luks_opts.cipher_mode); 10533e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 10543e308f20SDaniel P. Berrange ivcipheralg, 10553e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 10563e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10573e308f20SDaniel P. Berrange errp); 10583e308f20SDaniel P. Berrange 10593e308f20SDaniel P. Berrange if (!block->ivgen) { 10603e308f20SDaniel P. Berrange goto error; 10613e308f20SDaniel P. Berrange } 10623e308f20SDaniel P. Berrange 10633e308f20SDaniel P. Berrange 10643e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 10653e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 10663e308f20SDaniel P. Berrange */ 10673e308f20SDaniel P. Berrange luks->header.master_key_iterations = 10683e308f20SDaniel P. Berrange qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 10693e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10703e308f20SDaniel P. Berrange luks->header.master_key_salt, 10713e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10723e308f20SDaniel P. Berrange &local_err); 10733e308f20SDaniel P. Berrange if (local_err) { 10743e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10753e308f20SDaniel P. Berrange goto error; 10763e308f20SDaniel P. Berrange } 10773e308f20SDaniel P. Berrange 10783e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 10793e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 10803e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 10813e308f20SDaniel P. Berrange * in total time to check all keys */ 10823e308f20SDaniel P. Berrange luks->header.master_key_iterations /= 8; 10833e308f20SDaniel P. Berrange luks->header.master_key_iterations = MAX( 10843e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10853e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 10863e308f20SDaniel P. Berrange 10873e308f20SDaniel P. Berrange 10883e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 10893e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 10903e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 10913e308f20SDaniel P. Berrange * valid master key 10923e308f20SDaniel P. Berrange */ 10933e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 10943e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10953e308f20SDaniel P. Berrange luks->header.master_key_salt, 10963e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10973e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10983e308f20SDaniel P. Berrange luks->header.master_key_digest, 10993e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 11003e308f20SDaniel P. Berrange errp) < 0) { 11013e308f20SDaniel P. Berrange goto error; 11023e308f20SDaniel P. Berrange } 11033e308f20SDaniel P. Berrange 11043e308f20SDaniel P. Berrange 11053e308f20SDaniel P. Berrange /* Although LUKS has multiple key slots, we're just going 11063e308f20SDaniel P. Berrange * to use the first key slot */ 11073e308f20SDaniel P. Berrange splitkeylen = luks->header.key_bytes * QCRYPTO_BLOCK_LUKS_STRIPES; 11083e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 11093e308f20SDaniel P. Berrange luks->header.key_slots[i].active = i == 0 ? 11103e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED : 11113e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 11123e308f20SDaniel P. Berrange luks->header.key_slots[i].stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 11133e308f20SDaniel P. Berrange 11143e308f20SDaniel P. Berrange /* This calculation doesn't match that shown in the spec, 11153e308f20SDaniel P. Berrange * but instead follows the cryptsetup implementation. 11163e308f20SDaniel P. Berrange */ 11173e308f20SDaniel P. Berrange luks->header.key_slots[i].key_offset = 11183e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11193e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1120207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 11213e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11223e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i); 11233e308f20SDaniel P. Berrange } 11243e308f20SDaniel P. Berrange 11253e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.key_slots[0].salt, 11263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11273e308f20SDaniel P. Berrange errp) < 0) { 11283e308f20SDaniel P. Berrange goto error; 11293e308f20SDaniel P. Berrange } 11303e308f20SDaniel P. Berrange 11313e308f20SDaniel P. Berrange /* Again we determine how many iterations are required to 11323e308f20SDaniel P. Berrange * hash the user password while consuming 1 second of compute 11333e308f20SDaniel P. Berrange * time */ 11343e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations = 11353e308f20SDaniel P. Berrange qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 11363e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11373e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11383e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11393e308f20SDaniel P. Berrange &local_err); 11403e308f20SDaniel P. Berrange if (local_err) { 11413e308f20SDaniel P. Berrange error_propagate(errp, local_err); 11423e308f20SDaniel P. Berrange goto error; 11433e308f20SDaniel P. Berrange } 11443e308f20SDaniel P. Berrange /* Why /= 2 ? That matches cryptsetup, but there's no 11453e308f20SDaniel P. Berrange * explanation why they chose /= 2... */ 11463e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations /= 2; 11473e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations = MAX( 11483e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations, 11493e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 11503e308f20SDaniel P. Berrange 11513e308f20SDaniel P. Berrange 11523e308f20SDaniel P. Berrange /* Generate a key that we'll use to encrypt the master 11533e308f20SDaniel P. Berrange * key, from the user's password 11543e308f20SDaniel P. Berrange */ 11553e308f20SDaniel P. Berrange slotkey = g_new0(uint8_t, luks->header.key_bytes); 11563e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 11573e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11583e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11593e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11603e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations, 11613e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11623e308f20SDaniel P. Berrange errp) < 0) { 11633e308f20SDaniel P. Berrange goto error; 11643e308f20SDaniel P. Berrange } 11653e308f20SDaniel P. Berrange 11663e308f20SDaniel P. Berrange 11673e308f20SDaniel P. Berrange /* Setup the encryption objects needed to encrypt the 11683e308f20SDaniel P. Berrange * master key material 11693e308f20SDaniel P. Berrange */ 11703e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(luks_opts.cipher_alg, 11713e308f20SDaniel P. Berrange luks_opts.cipher_mode, 11723e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11733e308f20SDaniel P. Berrange errp); 11743e308f20SDaniel P. Berrange if (!cipher) { 11753e308f20SDaniel P. Berrange goto error; 11763e308f20SDaniel P. Berrange } 11773e308f20SDaniel P. Berrange 11783e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 11793e308f20SDaniel P. Berrange ivcipheralg, 11803e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 11813e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11823e308f20SDaniel P. Berrange errp); 11833e308f20SDaniel P. Berrange if (!ivgen) { 11843e308f20SDaniel P. Berrange goto error; 11853e308f20SDaniel P. Berrange } 11863e308f20SDaniel P. Berrange 11873e308f20SDaniel P. Berrange /* Before storing the master key, we need to vastly 11883e308f20SDaniel P. Berrange * increase its size, as protection against forensic 11893e308f20SDaniel P. Berrange * disk data recovery */ 11903e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 11913e308f20SDaniel P. Berrange 11923e308f20SDaniel P. Berrange if (qcrypto_afsplit_encode(luks_opts.hash_alg, 11933e308f20SDaniel P. Berrange luks->header.key_bytes, 11943e308f20SDaniel P. Berrange luks->header.key_slots[0].stripes, 11953e308f20SDaniel P. Berrange masterkey, 11963e308f20SDaniel P. Berrange splitkey, 11973e308f20SDaniel P. Berrange errp) < 0) { 11983e308f20SDaniel P. Berrange goto error; 11993e308f20SDaniel P. Berrange } 12003e308f20SDaniel P. Berrange 12013e308f20SDaniel P. Berrange /* Now we encrypt the split master key with the key generated 12023e308f20SDaniel P. Berrange * from the user's password, before storing it */ 12033e308f20SDaniel P. Berrange if (qcrypto_block_encrypt_helper(cipher, block->niv, ivgen, 12043e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12053e308f20SDaniel P. Berrange 0, 12063e308f20SDaniel P. Berrange splitkey, 12073e308f20SDaniel P. Berrange splitkeylen, 12083e308f20SDaniel P. Berrange errp) < 0) { 12093e308f20SDaniel P. Berrange goto error; 12103e308f20SDaniel P. Berrange } 12113e308f20SDaniel P. Berrange 12123e308f20SDaniel P. Berrange 12133e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 12143e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 12153e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 12163e308f20SDaniel P. Berrange * to the nearest sector */ 12173e308f20SDaniel P. Berrange luks->header.payload_offset = 12183e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12193e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1220207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 12213e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12223e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * 12233e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 12243e308f20SDaniel P. Berrange 12253e308f20SDaniel P. Berrange block->payload_offset = luks->header.payload_offset * 12263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 12273e308f20SDaniel P. Berrange 12283e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 12293e308f20SDaniel P. Berrange initfunc(block, block->payload_offset, &local_err, opaque); 12303e308f20SDaniel P. Berrange if (local_err) { 12313e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12323e308f20SDaniel P. Berrange goto error; 12333e308f20SDaniel P. Berrange } 12343e308f20SDaniel P. Berrange 12353e308f20SDaniel P. Berrange /* Everything on disk uses Big Endian, so flip header fields 12363e308f20SDaniel P. Berrange * before writing them */ 12373e308f20SDaniel P. Berrange cpu_to_be16s(&luks->header.version); 12383e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.payload_offset); 12393e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_bytes); 12403e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.master_key_iterations); 12413e308f20SDaniel P. Berrange 12423e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12433e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].active); 12443e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].iterations); 12453e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].key_offset); 12463e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].stripes); 12473e308f20SDaniel P. Berrange } 12483e308f20SDaniel P. Berrange 12493e308f20SDaniel P. Berrange 12503e308f20SDaniel P. Berrange /* Write out the partition header and key slot headers */ 12513e308f20SDaniel P. Berrange writefunc(block, 0, 12523e308f20SDaniel P. Berrange (const uint8_t *)&luks->header, 12533e308f20SDaniel P. Berrange sizeof(luks->header), 12543e308f20SDaniel P. Berrange &local_err, 12553e308f20SDaniel P. Berrange opaque); 12563e308f20SDaniel P. Berrange 12573e308f20SDaniel P. Berrange /* Delay checking local_err until we've byte-swapped */ 12583e308f20SDaniel P. Berrange 12593e308f20SDaniel P. Berrange /* Byte swap the header back to native, in case we need 12603e308f20SDaniel P. Berrange * to read it again later */ 12613e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 12623e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.payload_offset); 12633e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_bytes); 12643e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 12653e308f20SDaniel P. Berrange 12663e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12673e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 12683e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 12693e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].key_offset); 12703e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 12713e308f20SDaniel P. Berrange } 12723e308f20SDaniel P. Berrange 12733e308f20SDaniel P. Berrange if (local_err) { 12743e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12753e308f20SDaniel P. Berrange goto error; 12763e308f20SDaniel P. Berrange } 12773e308f20SDaniel P. Berrange 12783e308f20SDaniel P. Berrange /* Write out the master key material, starting at the 12793e308f20SDaniel P. Berrange * sector immediately following the partition header. */ 12803e308f20SDaniel P. Berrange if (writefunc(block, 12813e308f20SDaniel P. Berrange luks->header.key_slots[0].key_offset * 12823e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12833e308f20SDaniel P. Berrange splitkey, splitkeylen, 12843e308f20SDaniel P. Berrange errp, 12853e308f20SDaniel P. Berrange opaque) != splitkeylen) { 12863e308f20SDaniel P. Berrange goto error; 12873e308f20SDaniel P. Berrange } 12883e308f20SDaniel P. Berrange 1289*40c85028SDaniel P. Berrange luks->cipher_alg = luks_opts.cipher_alg; 1290*40c85028SDaniel P. Berrange luks->cipher_mode = luks_opts.cipher_mode; 1291*40c85028SDaniel P. Berrange luks->ivgen_alg = luks_opts.ivgen_alg; 1292*40c85028SDaniel P. Berrange luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 1293*40c85028SDaniel P. Berrange luks->hash_alg = luks_opts.hash_alg; 1294*40c85028SDaniel P. Berrange 12953e308f20SDaniel P. Berrange memset(masterkey, 0, luks->header.key_bytes); 12963e308f20SDaniel P. Berrange g_free(masterkey); 12973e308f20SDaniel P. Berrange memset(slotkey, 0, luks->header.key_bytes); 12983e308f20SDaniel P. Berrange g_free(slotkey); 12993e308f20SDaniel P. Berrange g_free(splitkey); 13003e308f20SDaniel P. Berrange g_free(password); 13013e308f20SDaniel P. Berrange g_free(cipher_mode_spec); 13023e308f20SDaniel P. Berrange 13033e308f20SDaniel P. Berrange qcrypto_ivgen_free(ivgen); 13043e308f20SDaniel P. Berrange qcrypto_cipher_free(cipher); 13053e308f20SDaniel P. Berrange 13063e308f20SDaniel P. Berrange return 0; 13073e308f20SDaniel P. Berrange 13083e308f20SDaniel P. Berrange error: 13093e308f20SDaniel P. Berrange if (masterkey) { 13103e308f20SDaniel P. Berrange memset(masterkey, 0, luks->header.key_bytes); 13113e308f20SDaniel P. Berrange } 13123e308f20SDaniel P. Berrange g_free(masterkey); 13133e308f20SDaniel P. Berrange if (slotkey) { 13143e308f20SDaniel P. Berrange memset(slotkey, 0, luks->header.key_bytes); 13153e308f20SDaniel P. Berrange } 13163e308f20SDaniel P. Berrange g_free(slotkey); 13173e308f20SDaniel P. Berrange g_free(splitkey); 13183e308f20SDaniel P. Berrange g_free(password); 13193e308f20SDaniel P. Berrange g_free(cipher_mode_spec); 13203e308f20SDaniel P. Berrange 13213e308f20SDaniel P. Berrange qcrypto_ivgen_free(ivgen); 13223e308f20SDaniel P. Berrange qcrypto_cipher_free(cipher); 13233e308f20SDaniel P. Berrange 13243e308f20SDaniel P. Berrange g_free(luks); 13253e308f20SDaniel P. Berrange return -1; 13263e308f20SDaniel P. Berrange } 13273e308f20SDaniel P. Berrange 13283e308f20SDaniel P. Berrange 1329*40c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 1330*40c85028SDaniel P. Berrange QCryptoBlockInfo *info, 1331*40c85028SDaniel P. Berrange Error **errp) 1332*40c85028SDaniel P. Berrange { 1333*40c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 1334*40c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 1335*40c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlotList *slots = NULL, **prev = &info->u.luks.slots; 1336*40c85028SDaniel P. Berrange size_t i; 1337*40c85028SDaniel P. Berrange 1338*40c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 1339*40c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 1340*40c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 1341*40c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 1342*40c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 1343*40c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 1344*40c85028SDaniel P. Berrange } 1345*40c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 1346*40c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 1347*40c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 1348*40c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 1349*40c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 1350*40c85028SDaniel P. Berrange 1351*40c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1352*40c85028SDaniel P. Berrange slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1); 1353*40c85028SDaniel P. Berrange *prev = slots; 1354*40c85028SDaniel P. Berrange 1355*40c85028SDaniel P. Berrange slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 1356*40c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 1357*40c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1358*40c85028SDaniel P. Berrange slot->key_offset = luks->header.key_slots[i].key_offset 1359*40c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1360*40c85028SDaniel P. Berrange if (slot->active) { 1361*40c85028SDaniel P. Berrange slot->has_iters = true; 1362*40c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 1363*40c85028SDaniel P. Berrange slot->has_stripes = true; 1364*40c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 1365*40c85028SDaniel P. Berrange } 1366*40c85028SDaniel P. Berrange 1367*40c85028SDaniel P. Berrange prev = &slots->next; 1368*40c85028SDaniel P. Berrange } 1369*40c85028SDaniel P. Berrange 1370*40c85028SDaniel P. Berrange return 0; 1371*40c85028SDaniel P. Berrange } 1372*40c85028SDaniel P. Berrange 1373*40c85028SDaniel P. Berrange 13743e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 13753e308f20SDaniel P. Berrange { 13763e308f20SDaniel P. Berrange g_free(block->opaque); 13773e308f20SDaniel P. Berrange } 13783e308f20SDaniel P. Berrange 13793e308f20SDaniel P. Berrange 13803e308f20SDaniel P. Berrange static int 13813e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 13823e308f20SDaniel P. Berrange uint64_t startsector, 13833e308f20SDaniel P. Berrange uint8_t *buf, 13843e308f20SDaniel P. Berrange size_t len, 13853e308f20SDaniel P. Berrange Error **errp) 13863e308f20SDaniel P. Berrange { 13873e308f20SDaniel P. Berrange return qcrypto_block_decrypt_helper(block->cipher, 13883e308f20SDaniel P. Berrange block->niv, block->ivgen, 13893e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13903e308f20SDaniel P. Berrange startsector, buf, len, errp); 13913e308f20SDaniel P. Berrange } 13923e308f20SDaniel P. Berrange 13933e308f20SDaniel P. Berrange 13943e308f20SDaniel P. Berrange static int 13953e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 13963e308f20SDaniel P. Berrange uint64_t startsector, 13973e308f20SDaniel P. Berrange uint8_t *buf, 13983e308f20SDaniel P. Berrange size_t len, 13993e308f20SDaniel P. Berrange Error **errp) 14003e308f20SDaniel P. Berrange { 14013e308f20SDaniel P. Berrange return qcrypto_block_encrypt_helper(block->cipher, 14023e308f20SDaniel P. Berrange block->niv, block->ivgen, 14033e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 14043e308f20SDaniel P. Berrange startsector, buf, len, errp); 14053e308f20SDaniel P. Berrange } 14063e308f20SDaniel P. Berrange 14073e308f20SDaniel P. Berrange 14083e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 14093e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 14103e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 1411*40c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 14123e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 14133e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 14143e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 14153e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 14163e308f20SDaniel P. Berrange }; 1417