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