13e308f20SDaniel P. Berrange /* 23e308f20SDaniel P. Berrange * QEMU Crypto block device encryption LUKS format 33e308f20SDaniel P. Berrange * 43e308f20SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 53e308f20SDaniel P. Berrange * 63e308f20SDaniel P. Berrange * This library is free software; you can redistribute it and/or 73e308f20SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 83e308f20SDaniel P. Berrange * License as published by the Free Software Foundation; either 9b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 103e308f20SDaniel P. Berrange * 113e308f20SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 123e308f20SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 133e308f20SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143e308f20SDaniel P. Berrange * Lesser General Public License for more details. 153e308f20SDaniel P. Berrange * 163e308f20SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 173e308f20SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 183e308f20SDaniel P. Berrange * 193e308f20SDaniel P. Berrange */ 203e308f20SDaniel P. Berrange 213e308f20SDaniel P. Berrange #include "qemu/osdep.h" 22da34e65cSMarkus Armbruster #include "qapi/error.h" 2358369e22SPaolo Bonzini #include "qemu/bswap.h" 243e308f20SDaniel P. Berrange 25986bc8deSMichael S. Tsirkin #include "block-luks.h" 263e308f20SDaniel P. Berrange 273e308f20SDaniel P. Berrange #include "crypto/hash.h" 283e308f20SDaniel P. Berrange #include "crypto/afsplit.h" 293e308f20SDaniel P. Berrange #include "crypto/pbkdf.h" 303e308f20SDaniel P. Berrange #include "crypto/secret.h" 313e308f20SDaniel P. Berrange #include "crypto/random.h" 322ef950f9SFam Zheng #include "qemu/uuid.h" 333e308f20SDaniel P. Berrange 343e308f20SDaniel P. Berrange #include "qemu/coroutine.h" 353e308f20SDaniel P. Berrange 363e308f20SDaniel P. Berrange /* 373e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is 383e308f20SDaniel P. Berrange * 393e308f20SDaniel P. Berrange * docs/on-disk-format.pdf 403e308f20SDaniel P. Berrange * 413e308f20SDaniel P. Berrange * in 'cryptsetup' package source code 423e308f20SDaniel P. Berrange * 433e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated 443e308f20SDaniel P. Berrange * Oct 16, 2011. 453e308f20SDaniel P. Berrange */ 463e308f20SDaniel P. Berrange 473e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS; 483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSHeader QCryptoBlockLUKSHeader; 493e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot; 503e308f20SDaniel P. Berrange 513e308f20SDaniel P. Berrange 523e308f20SDaniel P. Berrange /* The following constants are all defined by the LUKS spec */ 533e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_VERSION 1 543e308f20SDaniel P. Berrange 553e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MAGIC_LEN 6 563e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN 32 573e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN 32 583e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN 32 593e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_DIGEST_LEN 20 603e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SALT_LEN 32 613e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_UUID_LEN 40 623e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS 8 633e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_STRIPES 4000 643e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS 1000 653e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS 1000 663e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET 4096 673e308f20SDaniel P. Berrange 683e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED 0x0000DEAD 693e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3 703e308f20SDaniel P. Berrange 713e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL 723e308f20SDaniel P. Berrange 733e308f20SDaniel P. Berrange static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = { 743e308f20SDaniel P. Berrange 'L', 'U', 'K', 'S', 0xBA, 0xBE 753e308f20SDaniel P. Berrange }; 763e308f20SDaniel P. Berrange 773e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap; 783e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap { 793e308f20SDaniel P. Berrange const char *name; 803e308f20SDaniel P. Berrange int id; 813e308f20SDaniel P. Berrange }; 823e308f20SDaniel P. Berrange 833e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap; 843e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap { 853e308f20SDaniel P. Berrange uint32_t key_bytes; 863e308f20SDaniel P. Berrange int id; 873e308f20SDaniel P. Berrange }; 883e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap; 893e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap { 903e308f20SDaniel P. Berrange const char *name; 913e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes; 923e308f20SDaniel P. Berrange }; 933e308f20SDaniel P. Berrange 943e308f20SDaniel P. Berrange 953e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 963e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = { 973e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 }, 983e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 }, 993e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 }, 1003e308f20SDaniel P. Berrange { 0, 0 }, 1013e308f20SDaniel P. Berrange }; 1023e308f20SDaniel P. Berrange 1033e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1043e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = { 1053e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 }, 1063e308f20SDaniel P. Berrange { 0, 0 }, 1073e308f20SDaniel P. Berrange }; 1083e308f20SDaniel P. Berrange 1093e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1103e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = { 1113e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 }, 1123e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 }, 1133e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 }, 1143e308f20SDaniel P. Berrange { 0, 0 }, 1153e308f20SDaniel P. Berrange }; 1163e308f20SDaniel P. Berrange 1173e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 1183e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = { 1193e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 }, 1203e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 }, 1213e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 }, 1223e308f20SDaniel P. Berrange { 0, 0 }, 1233e308f20SDaniel P. Berrange }; 1243e308f20SDaniel P. Berrange 1253e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap 1263e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = { 1273e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes }, 1283e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, 1293e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, 1303e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, 1313e308f20SDaniel P. Berrange }; 1323e308f20SDaniel P. Berrange 1333e308f20SDaniel P. Berrange 1343e308f20SDaniel P. Berrange /* 1353e308f20SDaniel P. Berrange * This struct is written to disk in big-endian format, 1363e308f20SDaniel P. Berrange * but operated upon in native-endian format. 1373e308f20SDaniel P. Berrange */ 1383e308f20SDaniel P. Berrange struct QCryptoBlockLUKSKeySlot { 1393e308f20SDaniel P. Berrange /* state of keyslot, enabled/disable */ 1403e308f20SDaniel P. Berrange uint32_t active; 1413e308f20SDaniel P. Berrange /* iterations for PBKDF2 */ 1423e308f20SDaniel P. Berrange uint32_t iterations; 1433e308f20SDaniel P. Berrange /* salt for PBKDF2 */ 1443e308f20SDaniel P. Berrange uint8_t salt[QCRYPTO_BLOCK_LUKS_SALT_LEN]; 1453e308f20SDaniel P. Berrange /* start sector of key material */ 146f0d3c362SMaxim Levitsky uint32_t key_offset_sector; 1473e308f20SDaniel P. Berrange /* number of anti-forensic stripes */ 1483e308f20SDaniel P. Berrange uint32_t stripes; 1495993e3beSGreg Kurz }; 1503e308f20SDaniel P. Berrange 1513e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); 1523e308f20SDaniel P. Berrange 1533e308f20SDaniel P. Berrange 1543e308f20SDaniel P. Berrange /* 1553e308f20SDaniel P. Berrange * This struct is written to disk in big-endian format, 1563e308f20SDaniel P. Berrange * but operated upon in native-endian format. 1573e308f20SDaniel P. Berrange */ 1583e308f20SDaniel P. Berrange struct QCryptoBlockLUKSHeader { 1593e308f20SDaniel P. Berrange /* 'L', 'U', 'K', 'S', '0xBA', '0xBE' */ 1603e308f20SDaniel P. Berrange char magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN]; 1613e308f20SDaniel P. Berrange 1623e308f20SDaniel P. Berrange /* LUKS version, currently 1 */ 1633e308f20SDaniel P. Berrange uint16_t version; 1643e308f20SDaniel P. Berrange 1653e308f20SDaniel P. Berrange /* cipher name specification (aes, etc) */ 1663e308f20SDaniel P. Berrange char cipher_name[QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN]; 1673e308f20SDaniel P. Berrange 1683e308f20SDaniel P. Berrange /* cipher mode specification (cbc-plain, xts-essiv:sha256, etc) */ 1693e308f20SDaniel P. Berrange char cipher_mode[QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN]; 1703e308f20SDaniel P. Berrange 1713e308f20SDaniel P. Berrange /* hash specification (sha256, etc) */ 1723e308f20SDaniel P. Berrange char hash_spec[QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN]; 1733e308f20SDaniel P. Berrange 1743e308f20SDaniel P. Berrange /* start offset of the volume data (in 512 byte sectors) */ 175f0d3c362SMaxim Levitsky uint32_t payload_offset_sector; 1763e308f20SDaniel P. Berrange 1773e308f20SDaniel P. Berrange /* Number of key bytes */ 178f0d3c362SMaxim Levitsky uint32_t master_key_len; 1793e308f20SDaniel P. Berrange 1803e308f20SDaniel P. Berrange /* master key checksum after PBKDF2 */ 1813e308f20SDaniel P. Berrange uint8_t master_key_digest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 1823e308f20SDaniel P. Berrange 1833e308f20SDaniel P. Berrange /* salt for master key PBKDF2 */ 1843e308f20SDaniel P. Berrange uint8_t master_key_salt[QCRYPTO_BLOCK_LUKS_SALT_LEN]; 1853e308f20SDaniel P. Berrange 1863e308f20SDaniel P. Berrange /* iterations for master key PBKDF2 */ 1873e308f20SDaniel P. Berrange uint32_t master_key_iterations; 1883e308f20SDaniel P. Berrange 1893e308f20SDaniel P. Berrange /* UUID of the partition in standard ASCII representation */ 1903e308f20SDaniel P. Berrange uint8_t uuid[QCRYPTO_BLOCK_LUKS_UUID_LEN]; 1913e308f20SDaniel P. Berrange 1923e308f20SDaniel P. Berrange /* key slots */ 1933e308f20SDaniel P. Berrange QCryptoBlockLUKSKeySlot key_slots[QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS]; 1945993e3beSGreg Kurz }; 1953e308f20SDaniel P. Berrange 1963e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592); 1973e308f20SDaniel P. Berrange 1983e308f20SDaniel P. Berrange 1993e308f20SDaniel P. Berrange struct QCryptoBlockLUKS { 2003e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header; 20140c85028SDaniel P. Berrange 2029d80e59dSMaxim Levitsky /* Main encryption algorithm used for encryption*/ 20340c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 2049d80e59dSMaxim Levitsky 2059d80e59dSMaxim Levitsky /* Mode of encryption for the selected encryption algorithm */ 20640c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 2079d80e59dSMaxim Levitsky 2089d80e59dSMaxim Levitsky /* Initialization vector generation algorithm */ 20940c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 2109d80e59dSMaxim Levitsky 2119d80e59dSMaxim Levitsky /* Hash algorithm used for IV generation*/ 21240c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 2139d80e59dSMaxim Levitsky 2149d80e59dSMaxim Levitsky /* 2159d80e59dSMaxim Levitsky * Encryption algorithm used for IV generation. 2169d80e59dSMaxim Levitsky * Usually the same as main encryption algorithm 2179d80e59dSMaxim Levitsky */ 2189d80e59dSMaxim Levitsky QCryptoCipherAlgorithm ivgen_cipher_alg; 2199d80e59dSMaxim Levitsky 2209d80e59dSMaxim Levitsky /* Hash algorithm used in pbkdf2 function */ 22140c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 2223e308f20SDaniel P. Berrange }; 2233e308f20SDaniel P. Berrange 2243e308f20SDaniel P. Berrange 2253e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name, 2263e308f20SDaniel P. Berrange QCryptoCipherMode mode, 2273e308f20SDaniel P. Berrange uint32_t key_bytes, 2283e308f20SDaniel P. Berrange Error **errp) 2293e308f20SDaniel P. Berrange { 2303e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2313e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2323e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2333e308f20SDaniel P. Berrange size_t i, j; 2343e308f20SDaniel P. Berrange 2353e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) { 2363e308f20SDaniel P. Berrange key_bytes /= 2; 2373e308f20SDaniel P. Berrange } 2383e308f20SDaniel P. Berrange 2393e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2403e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) { 2413e308f20SDaniel P. Berrange continue; 2423e308f20SDaniel P. Berrange } 2433e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2443e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) { 2453e308f20SDaniel P. Berrange return map[i].sizes[j].id; 2463e308f20SDaniel P. Berrange } 2473e308f20SDaniel P. Berrange } 2483e308f20SDaniel P. Berrange } 2493e308f20SDaniel P. Berrange 2503e308f20SDaniel P. Berrange error_setg(errp, "Algorithm %s with key size %d bytes not supported", 2513e308f20SDaniel P. Berrange name, key_bytes); 2523e308f20SDaniel P. Berrange return 0; 2533e308f20SDaniel P. Berrange } 2543e308f20SDaniel P. Berrange 2553e308f20SDaniel P. Berrange static const char * 2563e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg, 2573e308f20SDaniel P. Berrange Error **errp) 2583e308f20SDaniel P. Berrange { 2593e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2603e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2613e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2623e308f20SDaniel P. Berrange size_t i, j; 2633e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2643e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2653e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) { 2663e308f20SDaniel P. Berrange return map[i].name; 2673e308f20SDaniel P. Berrange } 2683e308f20SDaniel P. Berrange } 2693e308f20SDaniel P. Berrange } 2703e308f20SDaniel P. Berrange 2713e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported", 272977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(alg)); 2733e308f20SDaniel P. Berrange return NULL; 2743e308f20SDaniel P. Berrange } 2753e308f20SDaniel P. Berrange 2763e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can 2773e308f20SDaniel P. Berrange * make that function emit a more friendly error message */ 2783e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name, 279f7abe0ecSMarc-André Lureau const QEnumLookup *map, 2803e308f20SDaniel P. Berrange const char *type, 2813e308f20SDaniel P. Berrange Error **errp) 2823e308f20SDaniel P. Berrange { 2839ae33079SMarkus Armbruster int ret = qapi_enum_parse(map, name, -1, NULL); 2843e308f20SDaniel P. Berrange 2859ae33079SMarkus Armbruster if (ret < 0) { 2863e308f20SDaniel P. Berrange error_setg(errp, "%s %s not supported", type, name); 2873e308f20SDaniel P. Berrange return 0; 2883e308f20SDaniel P. Berrange } 2899ae33079SMarkus Armbruster return ret; 2909ae33079SMarkus Armbruster } 2913e308f20SDaniel P. Berrange 2923e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \ 2933e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 294f7abe0ecSMarc-André Lureau &QCryptoCipherMode_lookup, \ 2953e308f20SDaniel P. Berrange "Cipher mode", \ 2963e308f20SDaniel P. Berrange errp) 2973e308f20SDaniel P. Berrange 2983e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \ 2993e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 300f7abe0ecSMarc-André Lureau &QCryptoHashAlgorithm_lookup, \ 3013e308f20SDaniel P. Berrange "Hash algorithm", \ 3023e308f20SDaniel P. Berrange errp) 3033e308f20SDaniel P. Berrange 3043e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \ 3053e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 306f7abe0ecSMarc-André Lureau &QCryptoIVGenAlgorithm_lookup, \ 3073e308f20SDaniel P. Berrange "IV generator", \ 3083e308f20SDaniel P. Berrange errp) 3093e308f20SDaniel P. Berrange 3103e308f20SDaniel P. Berrange 3113e308f20SDaniel P. Berrange static bool 3123e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf, 3133e308f20SDaniel P. Berrange size_t buf_size) 3143e308f20SDaniel P. Berrange { 3153e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf; 3163e308f20SDaniel P. Berrange 3173e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) && 3183e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic, 3193e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 && 3203e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) { 3213e308f20SDaniel P. Berrange return true; 3223e308f20SDaniel P. Berrange } else { 3233e308f20SDaniel P. Berrange return false; 3243e308f20SDaniel P. Berrange } 3253e308f20SDaniel P. Berrange } 3263e308f20SDaniel P. Berrange 3273e308f20SDaniel P. Berrange 3283e308f20SDaniel P. Berrange /** 3293e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV. 3303e308f20SDaniel P. Berrange * 3313e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV 3323e308f20SDaniel P. Berrange * may be different from the cipher length used for the block 3333e308f20SDaniel P. Berrange * encryption, becauses dm-crypt uses the hash digest length 3343e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher 3353e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as 3363e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest 3373e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined 3383e308f20SDaniel P. Berrange */ 3393e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm 3403e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher, 3413e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 3423e308f20SDaniel P. Berrange Error **errp) 3433e308f20SDaniel P. Berrange { 3443e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 3453e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher); 3463e308f20SDaniel P. Berrange if (digestlen == keylen) { 3473e308f20SDaniel P. Berrange return cipher; 3483e308f20SDaniel P. Berrange } 3493e308f20SDaniel P. Berrange 3503e308f20SDaniel P. Berrange switch (cipher) { 3513e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128: 3523e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192: 3533e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256: 3543e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3553e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) { 3563e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128; 3573e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3583e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) { 3593e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192; 3603e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3613e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) { 3623e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256; 3633e308f20SDaniel P. Berrange } else { 3643e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available", 3653e308f20SDaniel P. Berrange digestlen); 3663e308f20SDaniel P. Berrange return 0; 3673e308f20SDaniel P. Berrange } 3683e308f20SDaniel P. Berrange break; 3693e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128: 3703e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192: 3713e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256: 3723e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3733e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) { 3743e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128; 3753e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3763e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) { 3773e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192; 3783e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3793e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) { 3803e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256; 3813e308f20SDaniel P. Berrange } else { 3823e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available", 3833e308f20SDaniel P. Berrange digestlen); 3843e308f20SDaniel P. Berrange return 0; 3853e308f20SDaniel P. Berrange } 3863e308f20SDaniel P. Berrange break; 3873e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128: 3883e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192: 3893e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256: 3903e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3913e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) { 3923e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128; 3933e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3943e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) { 3953e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192; 3963e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3973e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) { 3983e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256; 3993e308f20SDaniel P. Berrange } else { 4003e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available", 4013e308f20SDaniel P. Berrange digestlen); 4023e308f20SDaniel P. Berrange return 0; 4033e308f20SDaniel P. Berrange } 4043e308f20SDaniel P. Berrange break; 4053e308f20SDaniel P. Berrange default: 4063e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv", 407977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(cipher)); 4083e308f20SDaniel P. Berrange return 0; 4093e308f20SDaniel P. Berrange } 4103e308f20SDaniel P. Berrange } 4113e308f20SDaniel P. Berrange 4123e308f20SDaniel P. Berrange /* 413*dde2c5afSMaxim Levitsky * Stores the main LUKS header, taking care of endianess 414*dde2c5afSMaxim Levitsky */ 415*dde2c5afSMaxim Levitsky static int 416*dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block, 417*dde2c5afSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 418*dde2c5afSMaxim Levitsky void *opaque, 419*dde2c5afSMaxim Levitsky Error **errp) 420*dde2c5afSMaxim Levitsky { 421*dde2c5afSMaxim Levitsky const QCryptoBlockLUKS *luks = block->opaque; 422*dde2c5afSMaxim Levitsky Error *local_err = NULL; 423*dde2c5afSMaxim Levitsky size_t i; 424*dde2c5afSMaxim Levitsky g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL; 425*dde2c5afSMaxim Levitsky 426*dde2c5afSMaxim Levitsky /* Create a copy of the header */ 427*dde2c5afSMaxim Levitsky hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1); 428*dde2c5afSMaxim Levitsky memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader)); 429*dde2c5afSMaxim Levitsky 430*dde2c5afSMaxim Levitsky /* 431*dde2c5afSMaxim Levitsky * Everything on disk uses Big Endian (tm), so flip header fields 432*dde2c5afSMaxim Levitsky * before writing them 433*dde2c5afSMaxim Levitsky */ 434*dde2c5afSMaxim Levitsky cpu_to_be16s(&hdr_copy->version); 435*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->payload_offset_sector); 436*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->master_key_len); 437*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->master_key_iterations); 438*dde2c5afSMaxim Levitsky 439*dde2c5afSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 440*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].active); 441*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].iterations); 442*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].key_offset_sector); 443*dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].stripes); 444*dde2c5afSMaxim Levitsky } 445*dde2c5afSMaxim Levitsky 446*dde2c5afSMaxim Levitsky /* Write out the partition header and key slot headers */ 447*dde2c5afSMaxim Levitsky writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy), 448*dde2c5afSMaxim Levitsky opaque, &local_err); 449*dde2c5afSMaxim Levitsky 450*dde2c5afSMaxim Levitsky if (local_err) { 451*dde2c5afSMaxim Levitsky error_propagate(errp, local_err); 452*dde2c5afSMaxim Levitsky return -1; 453*dde2c5afSMaxim Levitsky } 454*dde2c5afSMaxim Levitsky return 0; 455*dde2c5afSMaxim Levitsky } 456*dde2c5afSMaxim Levitsky 457*dde2c5afSMaxim Levitsky /* 458*dde2c5afSMaxim Levitsky * Loads the main LUKS header,and byteswaps it to native endianess 459*dde2c5afSMaxim Levitsky * And run basic sanity checks on it 460*dde2c5afSMaxim Levitsky */ 461*dde2c5afSMaxim Levitsky static int 462*dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block, 463*dde2c5afSMaxim Levitsky QCryptoBlockReadFunc readfunc, 464*dde2c5afSMaxim Levitsky void *opaque, 465*dde2c5afSMaxim Levitsky Error **errp) 466*dde2c5afSMaxim Levitsky { 467*dde2c5afSMaxim Levitsky ssize_t rv; 468*dde2c5afSMaxim Levitsky size_t i; 469*dde2c5afSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 470*dde2c5afSMaxim Levitsky 471*dde2c5afSMaxim Levitsky /* 472*dde2c5afSMaxim Levitsky * Read the entire LUKS header, minus the key material from 473*dde2c5afSMaxim Levitsky * the underlying device 474*dde2c5afSMaxim Levitsky */ 475*dde2c5afSMaxim Levitsky rv = readfunc(block, 0, 476*dde2c5afSMaxim Levitsky (uint8_t *)&luks->header, 477*dde2c5afSMaxim Levitsky sizeof(luks->header), 478*dde2c5afSMaxim Levitsky opaque, 479*dde2c5afSMaxim Levitsky errp); 480*dde2c5afSMaxim Levitsky if (rv < 0) { 481*dde2c5afSMaxim Levitsky return rv; 482*dde2c5afSMaxim Levitsky } 483*dde2c5afSMaxim Levitsky 484*dde2c5afSMaxim Levitsky /* 485*dde2c5afSMaxim Levitsky * The header is always stored in big-endian format, so 486*dde2c5afSMaxim Levitsky * convert everything to native 487*dde2c5afSMaxim Levitsky */ 488*dde2c5afSMaxim Levitsky be16_to_cpus(&luks->header.version); 489*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.payload_offset_sector); 490*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.master_key_len); 491*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.master_key_iterations); 492*dde2c5afSMaxim Levitsky 493*dde2c5afSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 494*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].active); 495*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].iterations); 496*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].key_offset_sector); 497*dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].stripes); 498*dde2c5afSMaxim Levitsky } 499*dde2c5afSMaxim Levitsky 500*dde2c5afSMaxim Levitsky return 0; 501*dde2c5afSMaxim Levitsky } 502*dde2c5afSMaxim Levitsky 503*dde2c5afSMaxim Levitsky /* 5043e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 5053e308f20SDaniel P. Berrange * the master encryption key from the key slot. 5063e308f20SDaniel P. Berrange * 5073e308f20SDaniel P. Berrange * Returns: 5083e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 5093e308f20SDaniel P. Berrange * with the provided password 5103e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 5113e308f20SDaniel P. Berrange * with the provided password 5123e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 5133e308f20SDaniel P. Berrange */ 5143e308f20SDaniel P. Berrange static int 5153e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 5167e60a6f5SMaxim Levitsky size_t slot_idx, 5173e308f20SDaniel P. Berrange const char *password, 5183e308f20SDaniel P. Berrange uint8_t *masterkey, 5193e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 5203e308f20SDaniel P. Berrange void *opaque, 5213e308f20SDaniel P. Berrange Error **errp) 5223e308f20SDaniel P. Berrange { 5233e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 5247e60a6f5SMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx]; 52557b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 5263e308f20SDaniel P. Berrange size_t splitkeylen; 52757b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 5283e308f20SDaniel P. Berrange ssize_t rv; 52957b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 5303e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 53157b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 5323e308f20SDaniel P. Berrange size_t niv; 5333e308f20SDaniel P. Berrange 5343e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 5353e308f20SDaniel P. Berrange return 0; 5363e308f20SDaniel P. Berrange } 5373e308f20SDaniel P. Berrange 5381ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 5393e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 5401ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 5413e308f20SDaniel P. Berrange 5423e308f20SDaniel P. Berrange /* 5433e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 5443e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 5453e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 5463e308f20SDaniel P. Berrange * the key is correct and validate the results of 5473e308f20SDaniel P. Berrange * decryption later. 5483e308f20SDaniel P. Berrange */ 5499d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 5503e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 5513e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 5523e308f20SDaniel P. Berrange slot->iterations, 5531ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 5543e308f20SDaniel P. Berrange errp) < 0) { 55557b9f113SDaniel P. Berrangé return -1; 5563e308f20SDaniel P. Berrange } 5573e308f20SDaniel P. Berrange 5583e308f20SDaniel P. Berrange /* 5593e308f20SDaniel P. Berrange * We need to read the master key material from the 5603e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 5613e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 5623e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 5633e308f20SDaniel P. Berrange * then encrypted. 5643e308f20SDaniel P. Berrange */ 5653e308f20SDaniel P. Berrange rv = readfunc(block, 566f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 5673e308f20SDaniel P. Berrange splitkey, splitkeylen, 568e4a3507eSDaniel P. Berrange opaque, 56937509233SFam Zheng errp); 5703e308f20SDaniel P. Berrange if (rv < 0) { 57157b9f113SDaniel P. Berrangé return -1; 5723e308f20SDaniel P. Berrange } 5733e308f20SDaniel P. Berrange 5743e308f20SDaniel P. Berrange 5753e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 5763e308f20SDaniel P. Berrange * the split master key material */ 5779d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 5789d80e59dSMaxim Levitsky luks->cipher_mode, 5799d80e59dSMaxim Levitsky possiblekey, 5809d80e59dSMaxim Levitsky luks->header.master_key_len, 5813e308f20SDaniel P. Berrange errp); 5823e308f20SDaniel P. Berrange if (!cipher) { 58357b9f113SDaniel P. Berrangé return -1; 5843e308f20SDaniel P. Berrange } 5853e308f20SDaniel P. Berrange 5869d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 5879d80e59dSMaxim Levitsky luks->cipher_mode); 5889d80e59dSMaxim Levitsky 5899d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 5909d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 5919d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 5929d80e59dSMaxim Levitsky possiblekey, 5939d80e59dSMaxim Levitsky luks->header.master_key_len, 5943e308f20SDaniel P. Berrange errp); 5953e308f20SDaniel P. Berrange if (!ivgen) { 59657b9f113SDaniel P. Berrangé return -1; 5973e308f20SDaniel P. Berrange } 5983e308f20SDaniel P. Berrange 5993e308f20SDaniel P. Berrange 6003e308f20SDaniel P. Berrange /* 6013e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 6023e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 6033e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 6043e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 6053e308f20SDaniel P. Berrange * key crosses a sector boundary. 6063e308f20SDaniel P. Berrange */ 6070270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 6083e308f20SDaniel P. Berrange niv, 6093e308f20SDaniel P. Berrange ivgen, 6103e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 6113e308f20SDaniel P. Berrange 0, 6123e308f20SDaniel P. Berrange splitkey, 6133e308f20SDaniel P. Berrange splitkeylen, 6143e308f20SDaniel P. Berrange errp) < 0) { 61557b9f113SDaniel P. Berrangé return -1; 6163e308f20SDaniel P. Berrange } 6173e308f20SDaniel P. Berrange 6183e308f20SDaniel P. Berrange /* 6193e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 6203e308f20SDaniel P. Berrange * it back together to get the actual master key. 6213e308f20SDaniel P. Berrange */ 6229d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 6231ddd52e4SMaxim Levitsky luks->header.master_key_len, 6243e308f20SDaniel P. Berrange slot->stripes, 6253e308f20SDaniel P. Berrange splitkey, 6263e308f20SDaniel P. Berrange masterkey, 6273e308f20SDaniel P. Berrange errp) < 0) { 62857b9f113SDaniel P. Berrangé return -1; 6293e308f20SDaniel P. Berrange } 6303e308f20SDaniel P. Berrange 6313e308f20SDaniel P. Berrange 6323e308f20SDaniel P. Berrange /* 6333e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 6343e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 6353e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 6363e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 6373e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 6383e308f20SDaniel P. Berrange * header 6393e308f20SDaniel P. Berrange */ 6409d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 6411ddd52e4SMaxim Levitsky masterkey, 6421ddd52e4SMaxim Levitsky luks->header.master_key_len, 6433e308f20SDaniel P. Berrange luks->header.master_key_salt, 6443e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 6453e308f20SDaniel P. Berrange luks->header.master_key_iterations, 6461ddd52e4SMaxim Levitsky keydigest, 6471ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 6483e308f20SDaniel P. Berrange errp) < 0) { 64957b9f113SDaniel P. Berrangé return -1; 6503e308f20SDaniel P. Berrange } 6513e308f20SDaniel P. Berrange 6523e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 6533e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 6543e308f20SDaniel P. Berrange /* Success, we got the right master key */ 65557b9f113SDaniel P. Berrangé return 1; 6563e308f20SDaniel P. Berrange } 6573e308f20SDaniel P. Berrange 6583e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 6593e308f20SDaniel P. Berrange * tell caller to try another slot */ 66057b9f113SDaniel P. Berrangé return 0; 6613e308f20SDaniel P. Berrange } 6623e308f20SDaniel P. Berrange 6633e308f20SDaniel P. Berrange 6643e308f20SDaniel P. Berrange /* 6653e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 6663e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 6673e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 6683e308f20SDaniel P. Berrange * 6693e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 6703e308f20SDaniel P. Berrange */ 6713e308f20SDaniel P. Berrange static int 6723e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 6733e308f20SDaniel P. Berrange const char *password, 6741ddd52e4SMaxim Levitsky uint8_t *masterkey, 6753e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 6763e308f20SDaniel P. Berrange void *opaque, 6773e308f20SDaniel P. Berrange Error **errp) 6783e308f20SDaniel P. Berrange { 6793e308f20SDaniel P. Berrange size_t i; 6803e308f20SDaniel P. Berrange int rv; 6813e308f20SDaniel P. Berrange 6823e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 6833e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 6847e60a6f5SMaxim Levitsky i, 6853e308f20SDaniel P. Berrange password, 6861ddd52e4SMaxim Levitsky masterkey, 6873e308f20SDaniel P. Berrange readfunc, 6883e308f20SDaniel P. Berrange opaque, 6893e308f20SDaniel P. Berrange errp); 6903e308f20SDaniel P. Berrange if (rv < 0) { 6913e308f20SDaniel P. Berrange goto error; 6923e308f20SDaniel P. Berrange } 6933e308f20SDaniel P. Berrange if (rv == 1) { 6943e308f20SDaniel P. Berrange return 0; 6953e308f20SDaniel P. Berrange } 6963e308f20SDaniel P. Berrange } 6973e308f20SDaniel P. Berrange 6983e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 6993e308f20SDaniel P. Berrange error: 7003e308f20SDaniel P. Berrange return -1; 7013e308f20SDaniel P. Berrange } 7023e308f20SDaniel P. Berrange 7033e308f20SDaniel P. Berrange 7043e308f20SDaniel P. Berrange static int 7053e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 7063e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 7071cd9a787SDaniel P. Berrange const char *optprefix, 7083e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 7093e308f20SDaniel P. Berrange void *opaque, 7103e308f20SDaniel P. Berrange unsigned int flags, 711c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 7123e308f20SDaniel P. Berrange Error **errp) 7133e308f20SDaniel P. Berrange { 7149d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 7153e308f20SDaniel P. Berrange Error *local_err = NULL; 71657b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 7173e308f20SDaniel P. Berrange char *ivgen_name, *ivhash_name; 71857b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 71970b2a1feSMaxim Levitsky g_autofree char *cipher_mode = NULL; 7203e308f20SDaniel P. Berrange 7213e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 7223e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 7231cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 7241cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 7253e308f20SDaniel P. Berrange return -1; 7263e308f20SDaniel P. Berrange } 7273e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 7283e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 7293e308f20SDaniel P. Berrange if (!password) { 7303e308f20SDaniel P. Berrange return -1; 7313e308f20SDaniel P. Berrange } 7323e308f20SDaniel P. Berrange } 7333e308f20SDaniel P. Berrange 7343e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 7353e308f20SDaniel P. Berrange block->opaque = luks; 7363e308f20SDaniel P. Berrange 737*dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 7383e308f20SDaniel P. Berrange goto fail; 7393e308f20SDaniel P. Berrange } 7403e308f20SDaniel P. Berrange 7413e308f20SDaniel P. Berrange if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 7423e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 7433e308f20SDaniel P. Berrange error_setg(errp, "Volume is not in LUKS format"); 7443e308f20SDaniel P. Berrange goto fail; 7453e308f20SDaniel P. Berrange } 7463e308f20SDaniel P. Berrange if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 7473e308f20SDaniel P. Berrange error_setg(errp, "LUKS version %" PRIu32 " is not supported", 7483e308f20SDaniel P. Berrange luks->header.version); 7493e308f20SDaniel P. Berrange goto fail; 7503e308f20SDaniel P. Berrange } 7513e308f20SDaniel P. Berrange 75270b2a1feSMaxim Levitsky cipher_mode = g_strdup(luks->header.cipher_mode); 75370b2a1feSMaxim Levitsky 7543e308f20SDaniel P. Berrange /* 7553e308f20SDaniel P. Berrange * The cipher_mode header contains a string that we have 7563e308f20SDaniel P. Berrange * to further parse, of the format 7573e308f20SDaniel P. Berrange * 7583e308f20SDaniel P. Berrange * <cipher-mode>-<iv-generator>[:<iv-hash>] 7593e308f20SDaniel P. Berrange * 7603e308f20SDaniel P. Berrange * eg cbc-essiv:sha256, cbc-plain64 7613e308f20SDaniel P. Berrange */ 76270b2a1feSMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 7633e308f20SDaniel P. Berrange if (!ivgen_name) { 7643e308f20SDaniel P. Berrange error_setg(errp, "Unexpected cipher mode string format %s", 76570b2a1feSMaxim Levitsky cipher_mode); 7663e308f20SDaniel P. Berrange goto fail; 7673e308f20SDaniel P. Berrange } 7683e308f20SDaniel P. Berrange *ivgen_name = '\0'; 7693e308f20SDaniel P. Berrange ivgen_name++; 7703e308f20SDaniel P. Berrange 7713e308f20SDaniel P. Berrange ivhash_name = strchr(ivgen_name, ':'); 7723e308f20SDaniel P. Berrange if (!ivhash_name) { 7739d80e59dSMaxim Levitsky luks->ivgen_hash_alg = 0; 7743e308f20SDaniel P. Berrange } else { 7753e308f20SDaniel P. Berrange *ivhash_name = '\0'; 7763e308f20SDaniel P. Berrange ivhash_name++; 7773e308f20SDaniel P. Berrange 7789d80e59dSMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 7793e308f20SDaniel P. Berrange &local_err); 7803e308f20SDaniel P. Berrange if (local_err) { 7813e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7823e308f20SDaniel P. Berrange goto fail; 7833e308f20SDaniel P. Berrange } 7843e308f20SDaniel P. Berrange } 7853e308f20SDaniel P. Berrange 7869d80e59dSMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 7873e308f20SDaniel P. Berrange &local_err); 7883e308f20SDaniel P. Berrange if (local_err) { 7893e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7903e308f20SDaniel P. Berrange goto fail; 7913e308f20SDaniel P. Berrange } 7923e308f20SDaniel P. Berrange 7939d80e59dSMaxim Levitsky luks->cipher_alg = 794f0d3c362SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 7959d80e59dSMaxim Levitsky luks->cipher_mode, 796f0d3c362SMaxim Levitsky luks->header.master_key_len, 7973e308f20SDaniel P. Berrange &local_err); 7983e308f20SDaniel P. Berrange if (local_err) { 7993e308f20SDaniel P. Berrange error_propagate(errp, local_err); 8003e308f20SDaniel P. Berrange goto fail; 8013e308f20SDaniel P. Berrange } 8023e308f20SDaniel P. Berrange 8039d80e59dSMaxim Levitsky luks->hash_alg = 8049d80e59dSMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 8053e308f20SDaniel P. Berrange &local_err); 8063e308f20SDaniel P. Berrange if (local_err) { 8073e308f20SDaniel P. Berrange error_propagate(errp, local_err); 8083e308f20SDaniel P. Berrange goto fail; 8093e308f20SDaniel P. Berrange } 8103e308f20SDaniel P. Berrange 8119d80e59dSMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 8123e308f20SDaniel P. Berrange &local_err); 8133e308f20SDaniel P. Berrange if (local_err) { 8143e308f20SDaniel P. Berrange error_propagate(errp, local_err); 8153e308f20SDaniel P. Berrange goto fail; 8163e308f20SDaniel P. Berrange } 8173e308f20SDaniel P. Berrange 8189d80e59dSMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 8198b7cdba3SDaniel P. Berrange if (!ivhash_name) { 8208b7cdba3SDaniel P. Berrange error_setg(errp, "Missing IV generator hash specification"); 8218b7cdba3SDaniel P. Berrange goto fail; 8228b7cdba3SDaniel P. Berrange } 8239d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 8249d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 8259d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 8263e308f20SDaniel P. Berrange &local_err); 8273e308f20SDaniel P. Berrange if (local_err) { 8283e308f20SDaniel P. Berrange error_propagate(errp, local_err); 8293e308f20SDaniel P. Berrange goto fail; 8303e308f20SDaniel P. Berrange } 8313e308f20SDaniel P. Berrange } else { 8328b7cdba3SDaniel P. Berrange /* Note we parsed the ivhash_name earlier in the cipher_mode 8338b7cdba3SDaniel P. Berrange * spec string even with plain/plain64 ivgens, but we 8348b7cdba3SDaniel P. Berrange * will ignore it, since it is irrelevant for these ivgens. 8358b7cdba3SDaniel P. Berrange * This is for compat with dm-crypt which will silently 8368b7cdba3SDaniel P. Berrange * ignore hash names with these ivgens rather than report 8378b7cdba3SDaniel P. Berrange * an error about the invalid usage 8388b7cdba3SDaniel P. Berrange */ 8399d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 8403e308f20SDaniel P. Berrange } 8413e308f20SDaniel P. Berrange 8423e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 8433e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 8443e308f20SDaniel P. Berrange * and unlock the master key from that slot. 8453e308f20SDaniel P. Berrange */ 8461ddd52e4SMaxim Levitsky 8471ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 8481ddd52e4SMaxim Levitsky 8493e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 8503e308f20SDaniel P. Berrange password, 8511ddd52e4SMaxim Levitsky masterkey, 8523e308f20SDaniel P. Berrange readfunc, opaque, 8533e308f20SDaniel P. Berrange errp) < 0) { 8543e308f20SDaniel P. Berrange goto fail; 8553e308f20SDaniel P. Berrange } 8563e308f20SDaniel P. Berrange 8573e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 8583e308f20SDaniel P. Berrange * block device payload decryption objects 8593e308f20SDaniel P. Berrange */ 8609d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 8619d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 8629d80e59dSMaxim Levitsky luks->cipher_mode); 8639d80e59dSMaxim Levitsky 8649d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 8659d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 8669d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 8671ddd52e4SMaxim Levitsky masterkey, 8681ddd52e4SMaxim Levitsky luks->header.master_key_len, 8693e308f20SDaniel P. Berrange errp); 8703e308f20SDaniel P. Berrange if (!block->ivgen) { 8713e308f20SDaniel P. Berrange goto fail; 8723e308f20SDaniel P. Berrange } 8733e308f20SDaniel P. Berrange 87461dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 8759d80e59dSMaxim Levitsky luks->cipher_alg, 8769d80e59dSMaxim Levitsky luks->cipher_mode, 8771ddd52e4SMaxim Levitsky masterkey, 8781ddd52e4SMaxim Levitsky luks->header.master_key_len, 8791ddd52e4SMaxim Levitsky n_threads, 88061dd8a9aSMaxim Levitsky errp) < 0) { 8813e308f20SDaniel P. Berrange goto fail; 8823e308f20SDaniel P. Berrange } 8833e308f20SDaniel P. Berrange } 8843e308f20SDaniel P. Berrange 885850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 886f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 887850f49deSDaniel P. Berrange block->sector_size; 8883e308f20SDaniel P. Berrange 8893e308f20SDaniel P. Berrange return 0; 8903e308f20SDaniel P. Berrange 8913e308f20SDaniel P. Berrange fail: 892c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 8933e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 8943e308f20SDaniel P. Berrange g_free(luks); 89561dd8a9aSMaxim Levitsky return -1; 8963e308f20SDaniel P. Berrange } 8973e308f20SDaniel P. Berrange 8983e308f20SDaniel P. Berrange 8992ef950f9SFam Zheng static void 9002ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 9013e308f20SDaniel P. Berrange { 9022ef950f9SFam Zheng QemuUUID uuid; 9032ef950f9SFam Zheng qemu_uuid_generate(&uuid); 9042ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 9053e308f20SDaniel P. Berrange } 9063e308f20SDaniel P. Berrange 9073e308f20SDaniel P. Berrange static int 9083e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 9093e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 9101cd9a787SDaniel P. Berrange const char *optprefix, 9113e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 9123e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 9133e308f20SDaniel P. Berrange void *opaque, 9143e308f20SDaniel P. Berrange Error **errp) 9153e308f20SDaniel P. Berrange { 9163e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 9173e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 9183e308f20SDaniel P. Berrange Error *local_err = NULL; 91957b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 92057b9f113SDaniel P. Berrangé g_autofree uint8_t *slotkey = NULL; 92157b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 9223e308f20SDaniel P. Berrange size_t splitkeylen = 0; 9233e308f20SDaniel P. Berrange size_t i; 92457b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 92557b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 92657b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 9273e308f20SDaniel P. Berrange const char *cipher_alg; 9283e308f20SDaniel P. Berrange const char *cipher_mode; 9293e308f20SDaniel P. Berrange const char *ivgen_alg; 9303e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 9313e308f20SDaniel P. Berrange const char *hash_alg; 93257b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 93359b060beSDaniel P. Berrange uint64_t iters; 9343e308f20SDaniel P. Berrange 9353e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 9363bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 9372ab66cd5SDaniel P. Berrange luks_opts.iter_time = 2000; 9383bd18890SDaniel P. Berrange } 9393e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 9403e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 9413e308f20SDaniel P. Berrange } 9423e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 9433e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 9443e308f20SDaniel P. Berrange } 9453e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 9463e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 9473e308f20SDaniel P. Berrange } 9483e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 9493e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 9503e308f20SDaniel P. Berrange } 9518b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9528b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 9538b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 9548b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 9558b7cdba3SDaniel P. Berrange } 9568b7cdba3SDaniel P. Berrange } 9579d80e59dSMaxim Levitsky 9589d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 9599d80e59dSMaxim Levitsky block->opaque = luks; 9609d80e59dSMaxim Levitsky 9619d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 9629d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 9639d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 9649d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 9659d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 9669d80e59dSMaxim Levitsky 9679d80e59dSMaxim Levitsky 9688b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 9698b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 9708b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 9713e308f20SDaniel P. Berrange 9723e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 9731cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 9741cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 9759d80e59dSMaxim Levitsky goto error; 9763e308f20SDaniel P. Berrange } 9773e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 9783e308f20SDaniel P. Berrange if (!password) { 9799d80e59dSMaxim Levitsky goto error; 9803e308f20SDaniel P. Berrange } 9813e308f20SDaniel P. Berrange 9823e308f20SDaniel P. Berrange 9833e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 9843e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 9853e308f20SDaniel P. Berrange 9863e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 9873e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 9883e308f20SDaniel P. Berrange * it out to disk 9893e308f20SDaniel P. Berrange */ 9903e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 9912ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 9923e308f20SDaniel P. Berrange 9933e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 9943e308f20SDaniel P. Berrange errp); 9953e308f20SDaniel P. Berrange if (!cipher_alg) { 9963e308f20SDaniel P. Berrange goto error; 9973e308f20SDaniel P. Berrange } 9983e308f20SDaniel P. Berrange 999977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 1000977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 10013e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 1002977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 10033e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 10043e308f20SDaniel P. Berrange ivgen_hash_alg); 10053e308f20SDaniel P. Berrange } else { 10063e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 10073e308f20SDaniel P. Berrange } 1008977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 10093e308f20SDaniel P. Berrange 10103e308f20SDaniel P. Berrange 10113e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 10123e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 10133e308f20SDaniel P. Berrange cipher_alg); 10143e308f20SDaniel P. Berrange goto error; 10153e308f20SDaniel P. Berrange } 10163e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 10173e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 10183e308f20SDaniel P. Berrange cipher_mode_spec); 10193e308f20SDaniel P. Berrange goto error; 10203e308f20SDaniel P. Berrange } 10213e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 10223e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 10233e308f20SDaniel P. Berrange hash_alg); 10243e308f20SDaniel P. Berrange goto error; 10253e308f20SDaniel P. Berrange } 10263e308f20SDaniel P. Berrange 10273e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 10289d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 10299d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 10303e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 10313e308f20SDaniel P. Berrange &local_err); 10323e308f20SDaniel P. Berrange if (local_err) { 10333e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10343e308f20SDaniel P. Berrange goto error; 10353e308f20SDaniel P. Berrange } 10363e308f20SDaniel P. Berrange } else { 10379d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 10383e308f20SDaniel P. Berrange } 10393e308f20SDaniel P. Berrange 10403e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 10413e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 10423e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 10433e308f20SDaniel P. Berrange 1044f0d3c362SMaxim Levitsky luks->header.master_key_len = 1045f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 1046f0d3c362SMaxim Levitsky 10473e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 1048f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 10493e308f20SDaniel P. Berrange } 10503e308f20SDaniel P. Berrange 10513e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 10523e308f20SDaniel P. Berrange * with PBKDF later 10533e308f20SDaniel P. Berrange */ 10543e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 10553e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10563e308f20SDaniel P. Berrange errp) < 0) { 10573e308f20SDaniel P. Berrange goto error; 10583e308f20SDaniel P. Berrange } 10593e308f20SDaniel P. Berrange 10603e308f20SDaniel P. Berrange /* Generate random master key */ 1061f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 10623e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 1063f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 10643e308f20SDaniel P. Berrange goto error; 10653e308f20SDaniel P. Berrange } 10663e308f20SDaniel P. Berrange 10673e308f20SDaniel P. Berrange 10683e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1069c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1070c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1071f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 10723e308f20SDaniel P. Berrange goto error; 10733e308f20SDaniel P. Berrange } 10743e308f20SDaniel P. Berrange 10753e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 10763e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 10773e308f20SDaniel P. Berrange luks_opts.cipher_mode); 10783e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 10799d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 10803e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1081f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 10823e308f20SDaniel P. Berrange errp); 10833e308f20SDaniel P. Berrange 10843e308f20SDaniel P. Berrange if (!block->ivgen) { 10853e308f20SDaniel P. Berrange goto error; 10863e308f20SDaniel P. Berrange } 10873e308f20SDaniel P. Berrange 10883e308f20SDaniel P. Berrange 10893e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 10903e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 10913e308f20SDaniel P. Berrange */ 109259b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1093f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 10943e308f20SDaniel P. Berrange luks->header.master_key_salt, 10953e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1096e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 10973e308f20SDaniel P. Berrange &local_err); 10983e308f20SDaniel P. Berrange if (local_err) { 10993e308f20SDaniel P. Berrange error_propagate(errp, local_err); 11003e308f20SDaniel P. Berrange goto error; 11013e308f20SDaniel P. Berrange } 11023e308f20SDaniel P. Berrange 11033bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 11043bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 11053bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 11063bd18890SDaniel P. Berrange (unsigned long long)iters); 11073bd18890SDaniel P. Berrange goto error; 11083bd18890SDaniel P. Berrange } 11093bd18890SDaniel P. Berrange 11103bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 11113bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 11123bd18890SDaniel P. Berrange 11133e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 11143e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 11153e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 11163e308f20SDaniel P. Berrange * in total time to check all keys */ 111759b060beSDaniel P. Berrange iters /= 8; 111859b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 111959b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 112059b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 112159b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 112259b060beSDaniel P. Berrange goto error; 112359b060beSDaniel P. Berrange } 112459b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 112559b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 11263e308f20SDaniel P. Berrange 11273e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 11283e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 11293e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 11303e308f20SDaniel P. Berrange * valid master key 11313e308f20SDaniel P. Berrange */ 11323e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1133f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 11343e308f20SDaniel P. Berrange luks->header.master_key_salt, 11353e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11363e308f20SDaniel P. Berrange luks->header.master_key_iterations, 11373e308f20SDaniel P. Berrange luks->header.master_key_digest, 11383e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 11393e308f20SDaniel P. Berrange errp) < 0) { 11403e308f20SDaniel P. Berrange goto error; 11413e308f20SDaniel P. Berrange } 11423e308f20SDaniel P. Berrange 11433e308f20SDaniel P. Berrange 11443e308f20SDaniel P. Berrange /* Although LUKS has multiple key slots, we're just going 11453e308f20SDaniel P. Berrange * to use the first key slot */ 1146f0d3c362SMaxim Levitsky splitkeylen = luks->header.master_key_len * QCRYPTO_BLOCK_LUKS_STRIPES; 11473e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 11483e308f20SDaniel P. Berrange luks->header.key_slots[i].active = i == 0 ? 11493e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED : 11503e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 11513e308f20SDaniel P. Berrange luks->header.key_slots[i].stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 11523e308f20SDaniel P. Berrange 11533e308f20SDaniel P. Berrange /* This calculation doesn't match that shown in the spec, 11543e308f20SDaniel P. Berrange * but instead follows the cryptsetup implementation. 11553e308f20SDaniel P. Berrange */ 1156f0d3c362SMaxim Levitsky luks->header.key_slots[i].key_offset_sector = 11573e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11583e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1159207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 11603e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11613e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i); 11623e308f20SDaniel P. Berrange } 11633e308f20SDaniel P. Berrange 11643e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.key_slots[0].salt, 11653e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11663e308f20SDaniel P. Berrange errp) < 0) { 11673e308f20SDaniel P. Berrange goto error; 11683e308f20SDaniel P. Berrange } 11693e308f20SDaniel P. Berrange 11703e308f20SDaniel P. Berrange /* Again we determine how many iterations are required to 11713e308f20SDaniel P. Berrange * hash the user password while consuming 1 second of compute 11723e308f20SDaniel P. Berrange * time */ 117359b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 11743e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11753e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11763e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1177f0d3c362SMaxim Levitsky luks->header.master_key_len, 11783e308f20SDaniel P. Berrange &local_err); 11793e308f20SDaniel P. Berrange if (local_err) { 11803e308f20SDaniel P. Berrange error_propagate(errp, local_err); 11813e308f20SDaniel P. Berrange goto error; 11823e308f20SDaniel P. Berrange } 11833bd18890SDaniel P. Berrange 11843bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 11853bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 11863bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 11873bd18890SDaniel P. Berrange (unsigned long long)iters); 11883bd18890SDaniel P. Berrange goto error; 11893bd18890SDaniel P. Berrange } 11903bd18890SDaniel P. Berrange 11913bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 11923bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 11933bd18890SDaniel P. Berrange 119459b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 119559b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 119659b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 119759b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 119859b060beSDaniel P. Berrange goto error; 119959b060beSDaniel P. Berrange } 120059b060beSDaniel P. Berrange 120159b060beSDaniel P. Berrange luks->header.key_slots[0].iterations = 120259b060beSDaniel P. Berrange MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 12033e308f20SDaniel P. Berrange 12043e308f20SDaniel P. Berrange 12053e308f20SDaniel P. Berrange /* Generate a key that we'll use to encrypt the master 12063e308f20SDaniel P. Berrange * key, from the user's password 12073e308f20SDaniel P. Berrange */ 1208f0d3c362SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 12093e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 12103e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 12113e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 12123e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 12133e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations, 1214f0d3c362SMaxim Levitsky slotkey, luks->header.master_key_len, 12153e308f20SDaniel P. Berrange errp) < 0) { 12163e308f20SDaniel P. Berrange goto error; 12173e308f20SDaniel P. Berrange } 12183e308f20SDaniel P. Berrange 12193e308f20SDaniel P. Berrange 12203e308f20SDaniel P. Berrange /* Setup the encryption objects needed to encrypt the 12213e308f20SDaniel P. Berrange * master key material 12223e308f20SDaniel P. Berrange */ 12233e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(luks_opts.cipher_alg, 12243e308f20SDaniel P. Berrange luks_opts.cipher_mode, 1225f0d3c362SMaxim Levitsky slotkey, luks->header.master_key_len, 12263e308f20SDaniel P. Berrange errp); 12273e308f20SDaniel P. Berrange if (!cipher) { 12283e308f20SDaniel P. Berrange goto error; 12293e308f20SDaniel P. Berrange } 12303e308f20SDaniel P. Berrange 12313e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 12329d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 12333e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1234f0d3c362SMaxim Levitsky slotkey, luks->header.master_key_len, 12353e308f20SDaniel P. Berrange errp); 12363e308f20SDaniel P. Berrange if (!ivgen) { 12373e308f20SDaniel P. Berrange goto error; 12383e308f20SDaniel P. Berrange } 12393e308f20SDaniel P. Berrange 12403e308f20SDaniel P. Berrange /* Before storing the master key, we need to vastly 12413e308f20SDaniel P. Berrange * increase its size, as protection against forensic 12423e308f20SDaniel P. Berrange * disk data recovery */ 12433e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 12443e308f20SDaniel P. Berrange 12453e308f20SDaniel P. Berrange if (qcrypto_afsplit_encode(luks_opts.hash_alg, 1246f0d3c362SMaxim Levitsky luks->header.master_key_len, 12473e308f20SDaniel P. Berrange luks->header.key_slots[0].stripes, 12483e308f20SDaniel P. Berrange masterkey, 12493e308f20SDaniel P. Berrange splitkey, 12503e308f20SDaniel P. Berrange errp) < 0) { 12513e308f20SDaniel P. Berrange goto error; 12523e308f20SDaniel P. Berrange } 12533e308f20SDaniel P. Berrange 12543e308f20SDaniel P. Berrange /* Now we encrypt the split master key with the key generated 12553e308f20SDaniel P. Berrange * from the user's password, before storing it */ 12560270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 12573e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12583e308f20SDaniel P. Berrange 0, 12593e308f20SDaniel P. Berrange splitkey, 12603e308f20SDaniel P. Berrange splitkeylen, 12613e308f20SDaniel P. Berrange errp) < 0) { 12623e308f20SDaniel P. Berrange goto error; 12633e308f20SDaniel P. Berrange } 12643e308f20SDaniel P. Berrange 12653e308f20SDaniel P. Berrange 12663e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 12673e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 12683e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 12693e308f20SDaniel P. Berrange * to the nearest sector */ 1270f0d3c362SMaxim Levitsky luks->header.payload_offset_sector = 12713e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12723e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1273207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 12743e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12753e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * 12763e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 12773e308f20SDaniel P. Berrange 1278850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1279f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1280850f49deSDaniel P. Berrange block->sector_size; 12813e308f20SDaniel P. Berrange 12823e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1283e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 12843e308f20SDaniel P. Berrange if (local_err) { 12853e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12863e308f20SDaniel P. Berrange goto error; 12873e308f20SDaniel P. Berrange } 12883e308f20SDaniel P. Berrange 1289*dde2c5afSMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) { 12903e308f20SDaniel P. Berrange goto error; 12913e308f20SDaniel P. Berrange } 12923e308f20SDaniel P. Berrange 12933e308f20SDaniel P. Berrange /* Write out the master key material, starting at the 12943e308f20SDaniel P. Berrange * sector immediately following the partition header. */ 1295e4a3507eSDaniel P. Berrange if (writefunc(block, 1296f0d3c362SMaxim Levitsky luks->header.key_slots[0].key_offset_sector * 12973e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12983e308f20SDaniel P. Berrange splitkey, splitkeylen, 1299e4a3507eSDaniel P. Berrange opaque, 130037509233SFam Zheng errp) != splitkeylen) { 13013e308f20SDaniel P. Berrange goto error; 13023e308f20SDaniel P. Berrange } 13033e308f20SDaniel P. Berrange 1304f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 1305f0d3c362SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 13063e308f20SDaniel P. Berrange 13073e308f20SDaniel P. Berrange return 0; 13083e308f20SDaniel P. Berrange 13093e308f20SDaniel P. Berrange error: 13103e308f20SDaniel P. Berrange if (masterkey) { 1311f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 13123e308f20SDaniel P. Berrange } 13133e308f20SDaniel P. Berrange if (slotkey) { 1314f0d3c362SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 13153e308f20SDaniel P. Berrange } 13163e308f20SDaniel P. Berrange 1317c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1318b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1319b640adcaSVladimir Sementsov-Ogievskiy 13203e308f20SDaniel P. Berrange g_free(luks); 13213e308f20SDaniel P. Berrange return -1; 13223e308f20SDaniel P. Berrange } 13233e308f20SDaniel P. Berrange 13243e308f20SDaniel P. Berrange 132540c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 132640c85028SDaniel P. Berrange QCryptoBlockInfo *info, 132740c85028SDaniel P. Berrange Error **errp) 132840c85028SDaniel P. Berrange { 132940c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 133040c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 133140c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlotList *slots = NULL, **prev = &info->u.luks.slots; 133240c85028SDaniel P. Berrange size_t i; 133340c85028SDaniel P. Berrange 133440c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 133540c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 133640c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 133740c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 133840c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 133940c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 134040c85028SDaniel P. Berrange } 134140c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 134240c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 134340c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 134440c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 134540c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 134640c85028SDaniel P. Berrange 134740c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 134840c85028SDaniel P. Berrange slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1); 134940c85028SDaniel P. Berrange *prev = slots; 135040c85028SDaniel P. Berrange 135140c85028SDaniel P. Berrange slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 135240c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 135340c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1354f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 135540c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 135640c85028SDaniel P. Berrange if (slot->active) { 135740c85028SDaniel P. Berrange slot->has_iters = true; 135840c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 135940c85028SDaniel P. Berrange slot->has_stripes = true; 136040c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 136140c85028SDaniel P. Berrange } 136240c85028SDaniel P. Berrange 136340c85028SDaniel P. Berrange prev = &slots->next; 136440c85028SDaniel P. Berrange } 136540c85028SDaniel P. Berrange 136640c85028SDaniel P. Berrange return 0; 136740c85028SDaniel P. Berrange } 136840c85028SDaniel P. Berrange 136940c85028SDaniel P. Berrange 13703e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 13713e308f20SDaniel P. Berrange { 13723e308f20SDaniel P. Berrange g_free(block->opaque); 13733e308f20SDaniel P. Berrange } 13743e308f20SDaniel P. Berrange 13753e308f20SDaniel P. Berrange 13763e308f20SDaniel P. Berrange static int 13773e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 13784609742aSDaniel P. Berrange uint64_t offset, 13793e308f20SDaniel P. Berrange uint8_t *buf, 13803e308f20SDaniel P. Berrange size_t len, 13813e308f20SDaniel P. Berrange Error **errp) 13823e308f20SDaniel P. Berrange { 13834609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13844609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13850f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 13863e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13874609742aSDaniel P. Berrange offset, buf, len, errp); 13883e308f20SDaniel P. Berrange } 13893e308f20SDaniel P. Berrange 13903e308f20SDaniel P. Berrange 13913e308f20SDaniel P. Berrange static int 13923e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 13934609742aSDaniel P. Berrange uint64_t offset, 13943e308f20SDaniel P. Berrange uint8_t *buf, 13953e308f20SDaniel P. Berrange size_t len, 13963e308f20SDaniel P. Berrange Error **errp) 13973e308f20SDaniel P. Berrange { 13984609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13994609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 14000f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 14013e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 14024609742aSDaniel P. Berrange offset, buf, len, errp); 14033e308f20SDaniel P. Berrange } 14043e308f20SDaniel P. Berrange 14053e308f20SDaniel P. Berrange 14063e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 14073e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 14083e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 140940c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 14103e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 14113e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 14123e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 14133e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 14143e308f20SDaniel P. Berrange }; 1415