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 /* 4133e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 4143e308f20SDaniel P. Berrange * the master encryption key from the key slot. 4153e308f20SDaniel P. Berrange * 4163e308f20SDaniel P. Berrange * Returns: 4173e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 4183e308f20SDaniel P. Berrange * with the provided password 4193e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 4203e308f20SDaniel P. Berrange * with the provided password 4213e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 4223e308f20SDaniel P. Berrange */ 4233e308f20SDaniel P. Berrange static int 4243e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 4257e60a6f5SMaxim Levitsky size_t slot_idx, 4263e308f20SDaniel P. Berrange const char *password, 4273e308f20SDaniel P. Berrange uint8_t *masterkey, 4283e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 4293e308f20SDaniel P. Berrange void *opaque, 4303e308f20SDaniel P. Berrange Error **errp) 4313e308f20SDaniel P. Berrange { 4323e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 4337e60a6f5SMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx]; 43457b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 4353e308f20SDaniel P. Berrange size_t splitkeylen; 43657b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 4373e308f20SDaniel P. Berrange ssize_t rv; 43857b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 4393e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 44057b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 4413e308f20SDaniel P. Berrange size_t niv; 4423e308f20SDaniel P. Berrange 4433e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 4443e308f20SDaniel P. Berrange return 0; 4453e308f20SDaniel P. Berrange } 4463e308f20SDaniel P. Berrange 4471ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 4483e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 4491ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 4503e308f20SDaniel P. Berrange 4513e308f20SDaniel P. Berrange /* 4523e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 4533e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 4543e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 4553e308f20SDaniel P. Berrange * the key is correct and validate the results of 4563e308f20SDaniel P. Berrange * decryption later. 4573e308f20SDaniel P. Berrange */ 4589d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 4593e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 4603e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 4613e308f20SDaniel P. Berrange slot->iterations, 4621ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 4633e308f20SDaniel P. Berrange errp) < 0) { 46457b9f113SDaniel P. Berrangé return -1; 4653e308f20SDaniel P. Berrange } 4663e308f20SDaniel P. Berrange 4673e308f20SDaniel P. Berrange /* 4683e308f20SDaniel P. Berrange * We need to read the master key material from the 4693e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 4703e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 4713e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 4723e308f20SDaniel P. Berrange * then encrypted. 4733e308f20SDaniel P. Berrange */ 4743e308f20SDaniel P. Berrange rv = readfunc(block, 475f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 4763e308f20SDaniel P. Berrange splitkey, splitkeylen, 477e4a3507eSDaniel P. Berrange opaque, 47837509233SFam Zheng errp); 4793e308f20SDaniel P. Berrange if (rv < 0) { 48057b9f113SDaniel P. Berrangé return -1; 4813e308f20SDaniel P. Berrange } 4823e308f20SDaniel P. Berrange 4833e308f20SDaniel P. Berrange 4843e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 4853e308f20SDaniel P. Berrange * the split master key material */ 4869d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 4879d80e59dSMaxim Levitsky luks->cipher_mode, 4889d80e59dSMaxim Levitsky possiblekey, 4899d80e59dSMaxim Levitsky luks->header.master_key_len, 4903e308f20SDaniel P. Berrange errp); 4913e308f20SDaniel P. Berrange if (!cipher) { 49257b9f113SDaniel P. Berrangé return -1; 4933e308f20SDaniel P. Berrange } 4943e308f20SDaniel P. Berrange 4959d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 4969d80e59dSMaxim Levitsky luks->cipher_mode); 4979d80e59dSMaxim Levitsky 4989d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 4999d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 5009d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 5019d80e59dSMaxim Levitsky possiblekey, 5029d80e59dSMaxim Levitsky luks->header.master_key_len, 5033e308f20SDaniel P. Berrange errp); 5043e308f20SDaniel P. Berrange if (!ivgen) { 50557b9f113SDaniel P. Berrangé return -1; 5063e308f20SDaniel P. Berrange } 5073e308f20SDaniel P. Berrange 5083e308f20SDaniel P. Berrange 5093e308f20SDaniel P. Berrange /* 5103e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 5113e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 5123e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 5133e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 5143e308f20SDaniel P. Berrange * key crosses a sector boundary. 5153e308f20SDaniel P. Berrange */ 5160270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 5173e308f20SDaniel P. Berrange niv, 5183e308f20SDaniel P. Berrange ivgen, 5193e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 5203e308f20SDaniel P. Berrange 0, 5213e308f20SDaniel P. Berrange splitkey, 5223e308f20SDaniel P. Berrange splitkeylen, 5233e308f20SDaniel P. Berrange errp) < 0) { 52457b9f113SDaniel P. Berrangé return -1; 5253e308f20SDaniel P. Berrange } 5263e308f20SDaniel P. Berrange 5273e308f20SDaniel P. Berrange /* 5283e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 5293e308f20SDaniel P. Berrange * it back together to get the actual master key. 5303e308f20SDaniel P. Berrange */ 5319d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 5321ddd52e4SMaxim Levitsky luks->header.master_key_len, 5333e308f20SDaniel P. Berrange slot->stripes, 5343e308f20SDaniel P. Berrange splitkey, 5353e308f20SDaniel P. Berrange masterkey, 5363e308f20SDaniel P. Berrange errp) < 0) { 53757b9f113SDaniel P. Berrangé return -1; 5383e308f20SDaniel P. Berrange } 5393e308f20SDaniel P. Berrange 5403e308f20SDaniel P. Berrange 5413e308f20SDaniel P. Berrange /* 5423e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 5433e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 5443e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 5453e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 5463e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 5473e308f20SDaniel P. Berrange * header 5483e308f20SDaniel P. Berrange */ 5499d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 5501ddd52e4SMaxim Levitsky masterkey, 5511ddd52e4SMaxim Levitsky luks->header.master_key_len, 5523e308f20SDaniel P. Berrange luks->header.master_key_salt, 5533e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 5543e308f20SDaniel P. Berrange luks->header.master_key_iterations, 5551ddd52e4SMaxim Levitsky keydigest, 5561ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 5573e308f20SDaniel P. Berrange errp) < 0) { 55857b9f113SDaniel P. Berrangé return -1; 5593e308f20SDaniel P. Berrange } 5603e308f20SDaniel P. Berrange 5613e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 5623e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 5633e308f20SDaniel P. Berrange /* Success, we got the right master key */ 56457b9f113SDaniel P. Berrangé return 1; 5653e308f20SDaniel P. Berrange } 5663e308f20SDaniel P. Berrange 5673e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 5683e308f20SDaniel P. Berrange * tell caller to try another slot */ 56957b9f113SDaniel P. Berrangé return 0; 5703e308f20SDaniel P. Berrange } 5713e308f20SDaniel P. Berrange 5723e308f20SDaniel P. Berrange 5733e308f20SDaniel P. Berrange /* 5743e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 5753e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 5763e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 5773e308f20SDaniel P. Berrange * 5783e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 5793e308f20SDaniel P. Berrange */ 5803e308f20SDaniel P. Berrange static int 5813e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 5823e308f20SDaniel P. Berrange const char *password, 5831ddd52e4SMaxim Levitsky uint8_t *masterkey, 5843e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 5853e308f20SDaniel P. Berrange void *opaque, 5863e308f20SDaniel P. Berrange Error **errp) 5873e308f20SDaniel P. Berrange { 5883e308f20SDaniel P. Berrange size_t i; 5893e308f20SDaniel P. Berrange int rv; 5903e308f20SDaniel P. Berrange 5913e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 5923e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 5937e60a6f5SMaxim Levitsky i, 5943e308f20SDaniel P. Berrange password, 5951ddd52e4SMaxim Levitsky masterkey, 5963e308f20SDaniel P. Berrange readfunc, 5973e308f20SDaniel P. Berrange opaque, 5983e308f20SDaniel P. Berrange errp); 5993e308f20SDaniel P. Berrange if (rv < 0) { 6003e308f20SDaniel P. Berrange goto error; 6013e308f20SDaniel P. Berrange } 6023e308f20SDaniel P. Berrange if (rv == 1) { 6033e308f20SDaniel P. Berrange return 0; 6043e308f20SDaniel P. Berrange } 6053e308f20SDaniel P. Berrange } 6063e308f20SDaniel P. Berrange 6073e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 6083e308f20SDaniel P. Berrange error: 6093e308f20SDaniel P. Berrange return -1; 6103e308f20SDaniel P. Berrange } 6113e308f20SDaniel P. Berrange 6123e308f20SDaniel P. Berrange 6133e308f20SDaniel P. Berrange static int 6143e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 6153e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 6161cd9a787SDaniel P. Berrange const char *optprefix, 6173e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 6183e308f20SDaniel P. Berrange void *opaque, 6193e308f20SDaniel P. Berrange unsigned int flags, 620c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 6213e308f20SDaniel P. Berrange Error **errp) 6223e308f20SDaniel P. Berrange { 6239d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 6243e308f20SDaniel P. Berrange Error *local_err = NULL; 6253e308f20SDaniel P. Berrange size_t i; 62657b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 6273e308f20SDaniel P. Berrange char *ivgen_name, *ivhash_name; 62857b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 62970b2a1feSMaxim Levitsky g_autofree char *cipher_mode = NULL; 6303e308f20SDaniel P. Berrange 6313e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 6323e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 6331cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 6341cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 6353e308f20SDaniel P. Berrange return -1; 6363e308f20SDaniel P. Berrange } 6373e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 6383e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 6393e308f20SDaniel P. Berrange if (!password) { 6403e308f20SDaniel P. Berrange return -1; 6413e308f20SDaniel P. Berrange } 6423e308f20SDaniel P. Berrange } 6433e308f20SDaniel P. Berrange 6443e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 6453e308f20SDaniel P. Berrange block->opaque = luks; 6463e308f20SDaniel P. Berrange 6473e308f20SDaniel P. Berrange /* Read the entire LUKS header, minus the key material from 6483e308f20SDaniel P. Berrange * the underlying device */ 649*61dd8a9aSMaxim Levitsky if (readfunc(block, 0, 6503e308f20SDaniel P. Berrange (uint8_t *)&luks->header, 6513e308f20SDaniel P. Berrange sizeof(luks->header), 652e4a3507eSDaniel P. Berrange opaque, 653*61dd8a9aSMaxim Levitsky errp) < 0) { 6543e308f20SDaniel P. Berrange goto fail; 6553e308f20SDaniel P. Berrange } 6563e308f20SDaniel P. Berrange 6573e308f20SDaniel P. Berrange /* The header is always stored in big-endian format, so 6583e308f20SDaniel P. Berrange * convert everything to native */ 6593e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 660f0d3c362SMaxim Levitsky be32_to_cpus(&luks->header.payload_offset_sector); 661f0d3c362SMaxim Levitsky be32_to_cpus(&luks->header.master_key_len); 6623e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 6633e308f20SDaniel P. Berrange 6643e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 6653e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 6663e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 667f0d3c362SMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].key_offset_sector); 6683e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 6693e308f20SDaniel P. Berrange } 6703e308f20SDaniel P. Berrange 6713e308f20SDaniel P. Berrange if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 6723e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 6733e308f20SDaniel P. Berrange error_setg(errp, "Volume is not in LUKS format"); 6743e308f20SDaniel P. Berrange goto fail; 6753e308f20SDaniel P. Berrange } 6763e308f20SDaniel P. Berrange if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 6773e308f20SDaniel P. Berrange error_setg(errp, "LUKS version %" PRIu32 " is not supported", 6783e308f20SDaniel P. Berrange luks->header.version); 6793e308f20SDaniel P. Berrange goto fail; 6803e308f20SDaniel P. Berrange } 6813e308f20SDaniel P. Berrange 68270b2a1feSMaxim Levitsky cipher_mode = g_strdup(luks->header.cipher_mode); 68370b2a1feSMaxim Levitsky 6843e308f20SDaniel P. Berrange /* 6853e308f20SDaniel P. Berrange * The cipher_mode header contains a string that we have 6863e308f20SDaniel P. Berrange * to further parse, of the format 6873e308f20SDaniel P. Berrange * 6883e308f20SDaniel P. Berrange * <cipher-mode>-<iv-generator>[:<iv-hash>] 6893e308f20SDaniel P. Berrange * 6903e308f20SDaniel P. Berrange * eg cbc-essiv:sha256, cbc-plain64 6913e308f20SDaniel P. Berrange */ 69270b2a1feSMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 6933e308f20SDaniel P. Berrange if (!ivgen_name) { 6943e308f20SDaniel P. Berrange error_setg(errp, "Unexpected cipher mode string format %s", 69570b2a1feSMaxim Levitsky cipher_mode); 6963e308f20SDaniel P. Berrange goto fail; 6973e308f20SDaniel P. Berrange } 6983e308f20SDaniel P. Berrange *ivgen_name = '\0'; 6993e308f20SDaniel P. Berrange ivgen_name++; 7003e308f20SDaniel P. Berrange 7013e308f20SDaniel P. Berrange ivhash_name = strchr(ivgen_name, ':'); 7023e308f20SDaniel P. Berrange if (!ivhash_name) { 7039d80e59dSMaxim Levitsky luks->ivgen_hash_alg = 0; 7043e308f20SDaniel P. Berrange } else { 7053e308f20SDaniel P. Berrange *ivhash_name = '\0'; 7063e308f20SDaniel P. Berrange ivhash_name++; 7073e308f20SDaniel P. Berrange 7089d80e59dSMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 7093e308f20SDaniel P. Berrange &local_err); 7103e308f20SDaniel P. Berrange if (local_err) { 7113e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7123e308f20SDaniel P. Berrange goto fail; 7133e308f20SDaniel P. Berrange } 7143e308f20SDaniel P. Berrange } 7153e308f20SDaniel P. Berrange 7169d80e59dSMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 7173e308f20SDaniel P. Berrange &local_err); 7183e308f20SDaniel P. Berrange if (local_err) { 7193e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7203e308f20SDaniel P. Berrange goto fail; 7213e308f20SDaniel P. Berrange } 7223e308f20SDaniel P. Berrange 7239d80e59dSMaxim Levitsky luks->cipher_alg = 724f0d3c362SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 7259d80e59dSMaxim Levitsky luks->cipher_mode, 726f0d3c362SMaxim Levitsky luks->header.master_key_len, 7273e308f20SDaniel P. Berrange &local_err); 7283e308f20SDaniel P. Berrange if (local_err) { 7293e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7303e308f20SDaniel P. Berrange goto fail; 7313e308f20SDaniel P. Berrange } 7323e308f20SDaniel P. Berrange 7339d80e59dSMaxim Levitsky luks->hash_alg = 7349d80e59dSMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 7353e308f20SDaniel P. Berrange &local_err); 7363e308f20SDaniel P. Berrange if (local_err) { 7373e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7383e308f20SDaniel P. Berrange goto fail; 7393e308f20SDaniel P. Berrange } 7403e308f20SDaniel P. Berrange 7419d80e59dSMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 7423e308f20SDaniel P. Berrange &local_err); 7433e308f20SDaniel P. Berrange if (local_err) { 7443e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7453e308f20SDaniel P. Berrange goto fail; 7463e308f20SDaniel P. Berrange } 7473e308f20SDaniel P. Berrange 7489d80e59dSMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 7498b7cdba3SDaniel P. Berrange if (!ivhash_name) { 7508b7cdba3SDaniel P. Berrange error_setg(errp, "Missing IV generator hash specification"); 7518b7cdba3SDaniel P. Berrange goto fail; 7528b7cdba3SDaniel P. Berrange } 7539d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 7549d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 7559d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 7563e308f20SDaniel P. Berrange &local_err); 7573e308f20SDaniel P. Berrange if (local_err) { 7583e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7593e308f20SDaniel P. Berrange goto fail; 7603e308f20SDaniel P. Berrange } 7613e308f20SDaniel P. Berrange } else { 7628b7cdba3SDaniel P. Berrange /* Note we parsed the ivhash_name earlier in the cipher_mode 7638b7cdba3SDaniel P. Berrange * spec string even with plain/plain64 ivgens, but we 7648b7cdba3SDaniel P. Berrange * will ignore it, since it is irrelevant for these ivgens. 7658b7cdba3SDaniel P. Berrange * This is for compat with dm-crypt which will silently 7668b7cdba3SDaniel P. Berrange * ignore hash names with these ivgens rather than report 7678b7cdba3SDaniel P. Berrange * an error about the invalid usage 7688b7cdba3SDaniel P. Berrange */ 7699d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 7703e308f20SDaniel P. Berrange } 7713e308f20SDaniel P. Berrange 7723e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 7733e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 7743e308f20SDaniel P. Berrange * and unlock the master key from that slot. 7753e308f20SDaniel P. Berrange */ 7761ddd52e4SMaxim Levitsky 7771ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 7781ddd52e4SMaxim Levitsky 7793e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 7803e308f20SDaniel P. Berrange password, 7811ddd52e4SMaxim Levitsky masterkey, 7823e308f20SDaniel P. Berrange readfunc, opaque, 7833e308f20SDaniel P. Berrange errp) < 0) { 7843e308f20SDaniel P. Berrange goto fail; 7853e308f20SDaniel P. Berrange } 7863e308f20SDaniel P. Berrange 7873e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 7883e308f20SDaniel P. Berrange * block device payload decryption objects 7893e308f20SDaniel P. Berrange */ 7909d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 7919d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 7929d80e59dSMaxim Levitsky luks->cipher_mode); 7939d80e59dSMaxim Levitsky 7949d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 7959d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 7969d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 7971ddd52e4SMaxim Levitsky masterkey, 7981ddd52e4SMaxim Levitsky luks->header.master_key_len, 7993e308f20SDaniel P. Berrange errp); 8003e308f20SDaniel P. Berrange if (!block->ivgen) { 8013e308f20SDaniel P. Berrange goto fail; 8023e308f20SDaniel P. Berrange } 8033e308f20SDaniel P. Berrange 804*61dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 8059d80e59dSMaxim Levitsky luks->cipher_alg, 8069d80e59dSMaxim Levitsky luks->cipher_mode, 8071ddd52e4SMaxim Levitsky masterkey, 8081ddd52e4SMaxim Levitsky luks->header.master_key_len, 8091ddd52e4SMaxim Levitsky n_threads, 810*61dd8a9aSMaxim Levitsky errp) < 0) { 8113e308f20SDaniel P. Berrange goto fail; 8123e308f20SDaniel P. Berrange } 8133e308f20SDaniel P. Berrange } 8143e308f20SDaniel P. Berrange 815850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 816f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 817850f49deSDaniel P. Berrange block->sector_size; 8183e308f20SDaniel P. Berrange 8193e308f20SDaniel P. Berrange return 0; 8203e308f20SDaniel P. Berrange 8213e308f20SDaniel P. Berrange fail: 822c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 8233e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 8243e308f20SDaniel P. Berrange g_free(luks); 825*61dd8a9aSMaxim Levitsky return -1; 8263e308f20SDaniel P. Berrange } 8273e308f20SDaniel P. Berrange 8283e308f20SDaniel P. Berrange 8292ef950f9SFam Zheng static void 8302ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 8313e308f20SDaniel P. Berrange { 8322ef950f9SFam Zheng QemuUUID uuid; 8332ef950f9SFam Zheng qemu_uuid_generate(&uuid); 8342ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 8353e308f20SDaniel P. Berrange } 8363e308f20SDaniel P. Berrange 8373e308f20SDaniel P. Berrange static int 8383e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 8393e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 8401cd9a787SDaniel P. Berrange const char *optprefix, 8413e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 8423e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 8433e308f20SDaniel P. Berrange void *opaque, 8443e308f20SDaniel P. Berrange Error **errp) 8453e308f20SDaniel P. Berrange { 8463e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 8473e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 8483e308f20SDaniel P. Berrange Error *local_err = NULL; 84957b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 85057b9f113SDaniel P. Berrangé g_autofree uint8_t *slotkey = NULL; 85157b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 8523e308f20SDaniel P. Berrange size_t splitkeylen = 0; 8533e308f20SDaniel P. Berrange size_t i; 85457b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 85557b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 85657b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 8573e308f20SDaniel P. Berrange const char *cipher_alg; 8583e308f20SDaniel P. Berrange const char *cipher_mode; 8593e308f20SDaniel P. Berrange const char *ivgen_alg; 8603e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 8613e308f20SDaniel P. Berrange const char *hash_alg; 86257b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 86359b060beSDaniel P. Berrange uint64_t iters; 8643e308f20SDaniel P. Berrange 8653e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 8663bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 8672ab66cd5SDaniel P. Berrange luks_opts.iter_time = 2000; 8683bd18890SDaniel P. Berrange } 8693e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 8703e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 8713e308f20SDaniel P. Berrange } 8723e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 8733e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 8743e308f20SDaniel P. Berrange } 8753e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 8763e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 8773e308f20SDaniel P. Berrange } 8783e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 8793e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 8803e308f20SDaniel P. Berrange } 8818b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 8828b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 8838b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 8848b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 8858b7cdba3SDaniel P. Berrange } 8868b7cdba3SDaniel P. Berrange } 8879d80e59dSMaxim Levitsky 8889d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 8899d80e59dSMaxim Levitsky block->opaque = luks; 8909d80e59dSMaxim Levitsky 8919d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 8929d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 8939d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 8949d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 8959d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 8969d80e59dSMaxim Levitsky 8979d80e59dSMaxim Levitsky 8988b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 8998b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 9008b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 9013e308f20SDaniel P. Berrange 9023e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 9031cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 9041cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 9059d80e59dSMaxim Levitsky goto error; 9063e308f20SDaniel P. Berrange } 9073e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 9083e308f20SDaniel P. Berrange if (!password) { 9099d80e59dSMaxim Levitsky goto error; 9103e308f20SDaniel P. Berrange } 9113e308f20SDaniel P. Berrange 9123e308f20SDaniel P. Berrange 9133e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 9143e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 9153e308f20SDaniel P. Berrange 9163e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 9173e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 9183e308f20SDaniel P. Berrange * it out to disk 9193e308f20SDaniel P. Berrange */ 9203e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 9212ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 9223e308f20SDaniel P. Berrange 9233e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 9243e308f20SDaniel P. Berrange errp); 9253e308f20SDaniel P. Berrange if (!cipher_alg) { 9263e308f20SDaniel P. Berrange goto error; 9273e308f20SDaniel P. Berrange } 9283e308f20SDaniel P. Berrange 929977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 930977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 9313e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 932977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 9333e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 9343e308f20SDaniel P. Berrange ivgen_hash_alg); 9353e308f20SDaniel P. Berrange } else { 9363e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 9373e308f20SDaniel P. Berrange } 938977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 9393e308f20SDaniel P. Berrange 9403e308f20SDaniel P. Berrange 9413e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 9423e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 9433e308f20SDaniel P. Berrange cipher_alg); 9443e308f20SDaniel P. Berrange goto error; 9453e308f20SDaniel P. Berrange } 9463e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 9473e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 9483e308f20SDaniel P. Berrange cipher_mode_spec); 9493e308f20SDaniel P. Berrange goto error; 9503e308f20SDaniel P. Berrange } 9513e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 9523e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 9533e308f20SDaniel P. Berrange hash_alg); 9543e308f20SDaniel P. Berrange goto error; 9553e308f20SDaniel P. Berrange } 9563e308f20SDaniel P. Berrange 9573e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9589d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 9599d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 9603e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 9613e308f20SDaniel P. Berrange &local_err); 9623e308f20SDaniel P. Berrange if (local_err) { 9633e308f20SDaniel P. Berrange error_propagate(errp, local_err); 9643e308f20SDaniel P. Berrange goto error; 9653e308f20SDaniel P. Berrange } 9663e308f20SDaniel P. Berrange } else { 9679d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 9683e308f20SDaniel P. Berrange } 9693e308f20SDaniel P. Berrange 9703e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 9713e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 9723e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 9733e308f20SDaniel P. Berrange 974f0d3c362SMaxim Levitsky luks->header.master_key_len = 975f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 976f0d3c362SMaxim Levitsky 9773e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 978f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 9793e308f20SDaniel P. Berrange } 9803e308f20SDaniel P. Berrange 9813e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 9823e308f20SDaniel P. Berrange * with PBKDF later 9833e308f20SDaniel P. Berrange */ 9843e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 9853e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 9863e308f20SDaniel P. Berrange errp) < 0) { 9873e308f20SDaniel P. Berrange goto error; 9883e308f20SDaniel P. Berrange } 9893e308f20SDaniel P. Berrange 9903e308f20SDaniel P. Berrange /* Generate random master key */ 991f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 9923e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 993f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 9943e308f20SDaniel P. Berrange goto error; 9953e308f20SDaniel P. Berrange } 9963e308f20SDaniel P. Berrange 9973e308f20SDaniel P. Berrange 9983e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 999c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1000c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1001f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 10023e308f20SDaniel P. Berrange goto error; 10033e308f20SDaniel P. Berrange } 10043e308f20SDaniel P. Berrange 10053e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 10063e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 10073e308f20SDaniel P. Berrange luks_opts.cipher_mode); 10083e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 10099d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 10103e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1011f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 10123e308f20SDaniel P. Berrange errp); 10133e308f20SDaniel P. Berrange 10143e308f20SDaniel P. Berrange if (!block->ivgen) { 10153e308f20SDaniel P. Berrange goto error; 10163e308f20SDaniel P. Berrange } 10173e308f20SDaniel P. Berrange 10183e308f20SDaniel P. Berrange 10193e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 10203e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 10213e308f20SDaniel P. Berrange */ 102259b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1023f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 10243e308f20SDaniel P. Berrange luks->header.master_key_salt, 10253e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1026e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 10273e308f20SDaniel P. Berrange &local_err); 10283e308f20SDaniel P. Berrange if (local_err) { 10293e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10303e308f20SDaniel P. Berrange goto error; 10313e308f20SDaniel P. Berrange } 10323e308f20SDaniel P. Berrange 10333bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 10343bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 10353bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 10363bd18890SDaniel P. Berrange (unsigned long long)iters); 10373bd18890SDaniel P. Berrange goto error; 10383bd18890SDaniel P. Berrange } 10393bd18890SDaniel P. Berrange 10403bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 10413bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 10423bd18890SDaniel P. Berrange 10433e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 10443e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 10453e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 10463e308f20SDaniel P. Berrange * in total time to check all keys */ 104759b060beSDaniel P. Berrange iters /= 8; 104859b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 104959b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 105059b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 105159b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 105259b060beSDaniel P. Berrange goto error; 105359b060beSDaniel P. Berrange } 105459b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 105559b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 10563e308f20SDaniel P. Berrange 10573e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 10583e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 10593e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 10603e308f20SDaniel P. Berrange * valid master key 10613e308f20SDaniel P. Berrange */ 10623e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1063f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 10643e308f20SDaniel P. Berrange luks->header.master_key_salt, 10653e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10663e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10673e308f20SDaniel P. Berrange luks->header.master_key_digest, 10683e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 10693e308f20SDaniel P. Berrange errp) < 0) { 10703e308f20SDaniel P. Berrange goto error; 10713e308f20SDaniel P. Berrange } 10723e308f20SDaniel P. Berrange 10733e308f20SDaniel P. Berrange 10743e308f20SDaniel P. Berrange /* Although LUKS has multiple key slots, we're just going 10753e308f20SDaniel P. Berrange * to use the first key slot */ 1076f0d3c362SMaxim Levitsky splitkeylen = luks->header.master_key_len * QCRYPTO_BLOCK_LUKS_STRIPES; 10773e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10783e308f20SDaniel P. Berrange luks->header.key_slots[i].active = i == 0 ? 10793e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED : 10803e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 10813e308f20SDaniel P. Berrange luks->header.key_slots[i].stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 10823e308f20SDaniel P. Berrange 10833e308f20SDaniel P. Berrange /* This calculation doesn't match that shown in the spec, 10843e308f20SDaniel P. Berrange * but instead follows the cryptsetup implementation. 10853e308f20SDaniel P. Berrange */ 1086f0d3c362SMaxim Levitsky luks->header.key_slots[i].key_offset_sector = 10873e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 10883e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1089207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 10903e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 10913e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i); 10923e308f20SDaniel P. Berrange } 10933e308f20SDaniel P. Berrange 10943e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.key_slots[0].salt, 10953e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10963e308f20SDaniel P. Berrange errp) < 0) { 10973e308f20SDaniel P. Berrange goto error; 10983e308f20SDaniel P. Berrange } 10993e308f20SDaniel P. Berrange 11003e308f20SDaniel P. Berrange /* Again we determine how many iterations are required to 11013e308f20SDaniel P. Berrange * hash the user password while consuming 1 second of compute 11023e308f20SDaniel P. Berrange * time */ 110359b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 11043e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11053e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11063e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1107f0d3c362SMaxim Levitsky luks->header.master_key_len, 11083e308f20SDaniel P. Berrange &local_err); 11093e308f20SDaniel P. Berrange if (local_err) { 11103e308f20SDaniel P. Berrange error_propagate(errp, local_err); 11113e308f20SDaniel P. Berrange goto error; 11123e308f20SDaniel P. Berrange } 11133bd18890SDaniel P. Berrange 11143bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 11153bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 11163bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 11173bd18890SDaniel P. Berrange (unsigned long long)iters); 11183bd18890SDaniel P. Berrange goto error; 11193bd18890SDaniel P. Berrange } 11203bd18890SDaniel P. Berrange 11213bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 11223bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 11233bd18890SDaniel P. Berrange 112459b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 112559b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 112659b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 112759b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 112859b060beSDaniel P. Berrange goto error; 112959b060beSDaniel P. Berrange } 113059b060beSDaniel P. Berrange 113159b060beSDaniel P. Berrange luks->header.key_slots[0].iterations = 113259b060beSDaniel P. Berrange MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 11333e308f20SDaniel P. Berrange 11343e308f20SDaniel P. Berrange 11353e308f20SDaniel P. Berrange /* Generate a key that we'll use to encrypt the master 11363e308f20SDaniel P. Berrange * key, from the user's password 11373e308f20SDaniel P. Berrange */ 1138f0d3c362SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 11393e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 11403e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11413e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11423e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11433e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations, 1144f0d3c362SMaxim Levitsky slotkey, luks->header.master_key_len, 11453e308f20SDaniel P. Berrange errp) < 0) { 11463e308f20SDaniel P. Berrange goto error; 11473e308f20SDaniel P. Berrange } 11483e308f20SDaniel P. Berrange 11493e308f20SDaniel P. Berrange 11503e308f20SDaniel P. Berrange /* Setup the encryption objects needed to encrypt the 11513e308f20SDaniel P. Berrange * master key material 11523e308f20SDaniel P. Berrange */ 11533e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(luks_opts.cipher_alg, 11543e308f20SDaniel P. Berrange luks_opts.cipher_mode, 1155f0d3c362SMaxim Levitsky slotkey, luks->header.master_key_len, 11563e308f20SDaniel P. Berrange errp); 11573e308f20SDaniel P. Berrange if (!cipher) { 11583e308f20SDaniel P. Berrange goto error; 11593e308f20SDaniel P. Berrange } 11603e308f20SDaniel P. Berrange 11613e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 11629d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 11633e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1164f0d3c362SMaxim Levitsky slotkey, luks->header.master_key_len, 11653e308f20SDaniel P. Berrange errp); 11663e308f20SDaniel P. Berrange if (!ivgen) { 11673e308f20SDaniel P. Berrange goto error; 11683e308f20SDaniel P. Berrange } 11693e308f20SDaniel P. Berrange 11703e308f20SDaniel P. Berrange /* Before storing the master key, we need to vastly 11713e308f20SDaniel P. Berrange * increase its size, as protection against forensic 11723e308f20SDaniel P. Berrange * disk data recovery */ 11733e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 11743e308f20SDaniel P. Berrange 11753e308f20SDaniel P. Berrange if (qcrypto_afsplit_encode(luks_opts.hash_alg, 1176f0d3c362SMaxim Levitsky luks->header.master_key_len, 11773e308f20SDaniel P. Berrange luks->header.key_slots[0].stripes, 11783e308f20SDaniel P. Berrange masterkey, 11793e308f20SDaniel P. Berrange splitkey, 11803e308f20SDaniel P. Berrange errp) < 0) { 11813e308f20SDaniel P. Berrange goto error; 11823e308f20SDaniel P. Berrange } 11833e308f20SDaniel P. Berrange 11843e308f20SDaniel P. Berrange /* Now we encrypt the split master key with the key generated 11853e308f20SDaniel P. Berrange * from the user's password, before storing it */ 11860270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 11873e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 11883e308f20SDaniel P. Berrange 0, 11893e308f20SDaniel P. Berrange splitkey, 11903e308f20SDaniel P. Berrange splitkeylen, 11913e308f20SDaniel P. Berrange errp) < 0) { 11923e308f20SDaniel P. Berrange goto error; 11933e308f20SDaniel P. Berrange } 11943e308f20SDaniel P. Berrange 11953e308f20SDaniel P. Berrange 11963e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 11973e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 11983e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 11993e308f20SDaniel P. Berrange * to the nearest sector */ 1200f0d3c362SMaxim Levitsky luks->header.payload_offset_sector = 12013e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12023e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1203207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 12043e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12053e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * 12063e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 12073e308f20SDaniel P. Berrange 1208850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1209f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1210850f49deSDaniel P. Berrange block->sector_size; 12113e308f20SDaniel P. Berrange 12123e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1213e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 12143e308f20SDaniel P. Berrange if (local_err) { 12153e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12163e308f20SDaniel P. Berrange goto error; 12173e308f20SDaniel P. Berrange } 12183e308f20SDaniel P. Berrange 12193e308f20SDaniel P. Berrange /* Everything on disk uses Big Endian, so flip header fields 12203e308f20SDaniel P. Berrange * before writing them */ 12213e308f20SDaniel P. Berrange cpu_to_be16s(&luks->header.version); 1222f0d3c362SMaxim Levitsky cpu_to_be32s(&luks->header.payload_offset_sector); 1223f0d3c362SMaxim Levitsky cpu_to_be32s(&luks->header.master_key_len); 12243e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.master_key_iterations); 12253e308f20SDaniel P. Berrange 12263e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12273e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].active); 12283e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].iterations); 1229f0d3c362SMaxim Levitsky cpu_to_be32s(&luks->header.key_slots[i].key_offset_sector); 12303e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].stripes); 12313e308f20SDaniel P. Berrange } 12323e308f20SDaniel P. Berrange 12333e308f20SDaniel P. Berrange 12343e308f20SDaniel P. Berrange /* Write out the partition header and key slot headers */ 1235e4a3507eSDaniel P. Berrange writefunc(block, 0, 12363e308f20SDaniel P. Berrange (const uint8_t *)&luks->header, 12373e308f20SDaniel P. Berrange sizeof(luks->header), 1238e4a3507eSDaniel P. Berrange opaque, 123937509233SFam Zheng &local_err); 12403e308f20SDaniel P. Berrange 12413e308f20SDaniel P. Berrange /* Delay checking local_err until we've byte-swapped */ 12423e308f20SDaniel P. Berrange 12433e308f20SDaniel P. Berrange /* Byte swap the header back to native, in case we need 12443e308f20SDaniel P. Berrange * to read it again later */ 12453e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 1246f0d3c362SMaxim Levitsky be32_to_cpus(&luks->header.payload_offset_sector); 1247f0d3c362SMaxim Levitsky be32_to_cpus(&luks->header.master_key_len); 12483e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 12493e308f20SDaniel P. Berrange 12503e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12513e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 12523e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 1253f0d3c362SMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].key_offset_sector); 12543e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 12553e308f20SDaniel P. Berrange } 12563e308f20SDaniel P. Berrange 12573e308f20SDaniel P. Berrange if (local_err) { 12583e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12593e308f20SDaniel P. Berrange goto error; 12603e308f20SDaniel P. Berrange } 12613e308f20SDaniel P. Berrange 12623e308f20SDaniel P. Berrange /* Write out the master key material, starting at the 12633e308f20SDaniel P. Berrange * sector immediately following the partition header. */ 1264e4a3507eSDaniel P. Berrange if (writefunc(block, 1265f0d3c362SMaxim Levitsky luks->header.key_slots[0].key_offset_sector * 12663e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12673e308f20SDaniel P. Berrange splitkey, splitkeylen, 1268e4a3507eSDaniel P. Berrange opaque, 126937509233SFam Zheng errp) != splitkeylen) { 12703e308f20SDaniel P. Berrange goto error; 12713e308f20SDaniel P. Berrange } 12723e308f20SDaniel P. Berrange 1273f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 1274f0d3c362SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 12753e308f20SDaniel P. Berrange 12763e308f20SDaniel P. Berrange return 0; 12773e308f20SDaniel P. Berrange 12783e308f20SDaniel P. Berrange error: 12793e308f20SDaniel P. Berrange if (masterkey) { 1280f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 12813e308f20SDaniel P. Berrange } 12823e308f20SDaniel P. Berrange if (slotkey) { 1283f0d3c362SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 12843e308f20SDaniel P. Berrange } 12853e308f20SDaniel P. Berrange 1286c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1287b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1288b640adcaSVladimir Sementsov-Ogievskiy 12893e308f20SDaniel P. Berrange g_free(luks); 12903e308f20SDaniel P. Berrange return -1; 12913e308f20SDaniel P. Berrange } 12923e308f20SDaniel P. Berrange 12933e308f20SDaniel P. Berrange 129440c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 129540c85028SDaniel P. Berrange QCryptoBlockInfo *info, 129640c85028SDaniel P. Berrange Error **errp) 129740c85028SDaniel P. Berrange { 129840c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 129940c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 130040c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlotList *slots = NULL, **prev = &info->u.luks.slots; 130140c85028SDaniel P. Berrange size_t i; 130240c85028SDaniel P. Berrange 130340c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 130440c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 130540c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 130640c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 130740c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 130840c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 130940c85028SDaniel P. Berrange } 131040c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 131140c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 131240c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 131340c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 131440c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 131540c85028SDaniel P. Berrange 131640c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 131740c85028SDaniel P. Berrange slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1); 131840c85028SDaniel P. Berrange *prev = slots; 131940c85028SDaniel P. Berrange 132040c85028SDaniel P. Berrange slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 132140c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 132240c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1323f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 132440c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 132540c85028SDaniel P. Berrange if (slot->active) { 132640c85028SDaniel P. Berrange slot->has_iters = true; 132740c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 132840c85028SDaniel P. Berrange slot->has_stripes = true; 132940c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 133040c85028SDaniel P. Berrange } 133140c85028SDaniel P. Berrange 133240c85028SDaniel P. Berrange prev = &slots->next; 133340c85028SDaniel P. Berrange } 133440c85028SDaniel P. Berrange 133540c85028SDaniel P. Berrange return 0; 133640c85028SDaniel P. Berrange } 133740c85028SDaniel P. Berrange 133840c85028SDaniel P. Berrange 13393e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 13403e308f20SDaniel P. Berrange { 13413e308f20SDaniel P. Berrange g_free(block->opaque); 13423e308f20SDaniel P. Berrange } 13433e308f20SDaniel P. Berrange 13443e308f20SDaniel P. Berrange 13453e308f20SDaniel P. Berrange static int 13463e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 13474609742aSDaniel P. Berrange uint64_t offset, 13483e308f20SDaniel P. Berrange uint8_t *buf, 13493e308f20SDaniel P. Berrange size_t len, 13503e308f20SDaniel P. Berrange Error **errp) 13513e308f20SDaniel P. Berrange { 13524609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13534609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13540f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 13553e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13564609742aSDaniel P. Berrange offset, buf, len, errp); 13573e308f20SDaniel P. Berrange } 13583e308f20SDaniel P. Berrange 13593e308f20SDaniel P. Berrange 13603e308f20SDaniel P. Berrange static int 13613e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 13624609742aSDaniel P. Berrange uint64_t offset, 13633e308f20SDaniel P. Berrange uint8_t *buf, 13643e308f20SDaniel P. Berrange size_t len, 13653e308f20SDaniel P. Berrange Error **errp) 13663e308f20SDaniel P. Berrange { 13674609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13684609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13690f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 13703e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13714609742aSDaniel P. Berrange offset, buf, len, errp); 13723e308f20SDaniel P. Berrange } 13733e308f20SDaniel P. Berrange 13743e308f20SDaniel P. Berrange 13753e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 13763e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 13773e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 137840c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 13793e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 13803e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 13813e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 13823e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 13833e308f20SDaniel P. Berrange }; 1384