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 */ 1463e308f20SDaniel P. Berrange uint32_t key_offset; 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) */ 1753e308f20SDaniel P. Berrange uint32_t payload_offset; 1763e308f20SDaniel P. Berrange 1773e308f20SDaniel P. Berrange /* Number of key bytes */ 1783e308f20SDaniel P. Berrange uint32_t key_bytes; 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 20240c85028SDaniel P. Berrange /* Cache parsed versions of what's in header fields, 20340c85028SDaniel P. Berrange * as we can't rely on QCryptoBlock.cipher being 20440c85028SDaniel P. Berrange * non-NULL */ 20540c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 20640c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 20740c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 20840c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 20940c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 2103e308f20SDaniel P. Berrange }; 2113e308f20SDaniel P. Berrange 2123e308f20SDaniel P. Berrange 2133e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name, 2143e308f20SDaniel P. Berrange QCryptoCipherMode mode, 2153e308f20SDaniel P. Berrange uint32_t key_bytes, 2163e308f20SDaniel P. Berrange Error **errp) 2173e308f20SDaniel P. Berrange { 2183e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2193e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2203e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2213e308f20SDaniel P. Berrange size_t i, j; 2223e308f20SDaniel P. Berrange 2233e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) { 2243e308f20SDaniel P. Berrange key_bytes /= 2; 2253e308f20SDaniel P. Berrange } 2263e308f20SDaniel P. Berrange 2273e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2283e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) { 2293e308f20SDaniel P. Berrange continue; 2303e308f20SDaniel P. Berrange } 2313e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2323e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) { 2333e308f20SDaniel P. Berrange return map[i].sizes[j].id; 2343e308f20SDaniel P. Berrange } 2353e308f20SDaniel P. Berrange } 2363e308f20SDaniel P. Berrange } 2373e308f20SDaniel P. Berrange 2383e308f20SDaniel P. Berrange error_setg(errp, "Algorithm %s with key size %d bytes not supported", 2393e308f20SDaniel P. Berrange name, key_bytes); 2403e308f20SDaniel P. Berrange return 0; 2413e308f20SDaniel P. Berrange } 2423e308f20SDaniel P. Berrange 2433e308f20SDaniel P. Berrange static const char * 2443e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg, 2453e308f20SDaniel P. Berrange Error **errp) 2463e308f20SDaniel P. Berrange { 2473e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 2483e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 2493e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 2503e308f20SDaniel P. Berrange size_t i, j; 2513e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 2523e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 2533e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) { 2543e308f20SDaniel P. Berrange return map[i].name; 2553e308f20SDaniel P. Berrange } 2563e308f20SDaniel P. Berrange } 2573e308f20SDaniel P. Berrange } 2583e308f20SDaniel P. Berrange 2593e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported", 260977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(alg)); 2613e308f20SDaniel P. Berrange return NULL; 2623e308f20SDaniel P. Berrange } 2633e308f20SDaniel P. Berrange 2643e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can 2653e308f20SDaniel P. Berrange * make that function emit a more friendly error message */ 2663e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name, 267f7abe0ecSMarc-André Lureau const QEnumLookup *map, 2683e308f20SDaniel P. Berrange const char *type, 2693e308f20SDaniel P. Berrange Error **errp) 2703e308f20SDaniel P. Berrange { 2719ae33079SMarkus Armbruster int ret = qapi_enum_parse(map, name, -1, NULL); 2723e308f20SDaniel P. Berrange 2739ae33079SMarkus Armbruster if (ret < 0) { 2743e308f20SDaniel P. Berrange error_setg(errp, "%s %s not supported", type, name); 2753e308f20SDaniel P. Berrange return 0; 2763e308f20SDaniel P. Berrange } 2779ae33079SMarkus Armbruster return ret; 2789ae33079SMarkus Armbruster } 2793e308f20SDaniel P. Berrange 2803e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \ 2813e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 282f7abe0ecSMarc-André Lureau &QCryptoCipherMode_lookup, \ 2833e308f20SDaniel P. Berrange "Cipher mode", \ 2843e308f20SDaniel P. Berrange errp) 2853e308f20SDaniel P. Berrange 2863e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \ 2873e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 288f7abe0ecSMarc-André Lureau &QCryptoHashAlgorithm_lookup, \ 2893e308f20SDaniel P. Berrange "Hash algorithm", \ 2903e308f20SDaniel P. Berrange errp) 2913e308f20SDaniel P. Berrange 2923e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \ 2933e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 294f7abe0ecSMarc-André Lureau &QCryptoIVGenAlgorithm_lookup, \ 2953e308f20SDaniel P. Berrange "IV generator", \ 2963e308f20SDaniel P. Berrange errp) 2973e308f20SDaniel P. Berrange 2983e308f20SDaniel P. Berrange 2993e308f20SDaniel P. Berrange static bool 3003e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf, 3013e308f20SDaniel P. Berrange size_t buf_size) 3023e308f20SDaniel P. Berrange { 3033e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf; 3043e308f20SDaniel P. Berrange 3053e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) && 3063e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic, 3073e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 && 3083e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) { 3093e308f20SDaniel P. Berrange return true; 3103e308f20SDaniel P. Berrange } else { 3113e308f20SDaniel P. Berrange return false; 3123e308f20SDaniel P. Berrange } 3133e308f20SDaniel P. Berrange } 3143e308f20SDaniel P. Berrange 3153e308f20SDaniel P. Berrange 3163e308f20SDaniel P. Berrange /** 3173e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV. 3183e308f20SDaniel P. Berrange * 3193e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV 3203e308f20SDaniel P. Berrange * may be different from the cipher length used for the block 3213e308f20SDaniel P. Berrange * encryption, becauses dm-crypt uses the hash digest length 3223e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher 3233e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as 3243e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest 3253e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined 3263e308f20SDaniel P. Berrange */ 3273e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm 3283e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher, 3293e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 3303e308f20SDaniel P. Berrange Error **errp) 3313e308f20SDaniel P. Berrange { 3323e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 3333e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher); 3343e308f20SDaniel P. Berrange if (digestlen == keylen) { 3353e308f20SDaniel P. Berrange return cipher; 3363e308f20SDaniel P. Berrange } 3373e308f20SDaniel P. Berrange 3383e308f20SDaniel P. Berrange switch (cipher) { 3393e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128: 3403e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192: 3413e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256: 3423e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3433e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) { 3443e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128; 3453e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3463e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) { 3473e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192; 3483e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3493e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) { 3503e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256; 3513e308f20SDaniel P. Berrange } else { 3523e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available", 3533e308f20SDaniel P. Berrange digestlen); 3543e308f20SDaniel P. Berrange return 0; 3553e308f20SDaniel P. Berrange } 3563e308f20SDaniel P. Berrange break; 3573e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128: 3583e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192: 3593e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256: 3603e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3613e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) { 3623e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128; 3633e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3643e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) { 3653e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192; 3663e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3673e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) { 3683e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256; 3693e308f20SDaniel P. Berrange } else { 3703e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available", 3713e308f20SDaniel P. Berrange digestlen); 3723e308f20SDaniel P. Berrange return 0; 3733e308f20SDaniel P. Berrange } 3743e308f20SDaniel P. Berrange break; 3753e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128: 3763e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192: 3773e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256: 3783e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3793e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) { 3803e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128; 3813e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3823e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) { 3833e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192; 3843e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3853e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) { 3863e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256; 3873e308f20SDaniel P. Berrange } else { 3883e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available", 3893e308f20SDaniel P. Berrange digestlen); 3903e308f20SDaniel P. Berrange return 0; 3913e308f20SDaniel P. Berrange } 3923e308f20SDaniel P. Berrange break; 3933e308f20SDaniel P. Berrange default: 3943e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv", 395977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(cipher)); 3963e308f20SDaniel P. Berrange return 0; 3973e308f20SDaniel P. Berrange } 3983e308f20SDaniel P. Berrange } 3993e308f20SDaniel P. Berrange 4003e308f20SDaniel P. Berrange /* 4013e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 4023e308f20SDaniel P. Berrange * the master encryption key from the key slot. 4033e308f20SDaniel P. Berrange * 4043e308f20SDaniel P. Berrange * Returns: 4053e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 4063e308f20SDaniel P. Berrange * with the provided password 4073e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 4083e308f20SDaniel P. Berrange * with the provided password 4093e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 4103e308f20SDaniel P. Berrange */ 4113e308f20SDaniel P. Berrange static int 4123e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 4133e308f20SDaniel P. Berrange QCryptoBlockLUKSKeySlot *slot, 4143e308f20SDaniel P. Berrange const char *password, 4153e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg, 4163e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode, 4173e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 4183e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg, 4193e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg, 4203e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash, 4213e308f20SDaniel P. Berrange uint8_t *masterkey, 4223e308f20SDaniel P. Berrange size_t masterkeylen, 4233e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 4243e308f20SDaniel P. Berrange void *opaque, 4253e308f20SDaniel P. Berrange Error **errp) 4263e308f20SDaniel P. Berrange { 4273e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 428*57b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 4293e308f20SDaniel P. Berrange size_t splitkeylen; 430*57b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 4313e308f20SDaniel P. Berrange ssize_t rv; 432*57b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 4333e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 434*57b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 4353e308f20SDaniel P. Berrange size_t niv; 4363e308f20SDaniel P. Berrange 4373e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 4383e308f20SDaniel P. Berrange return 0; 4393e308f20SDaniel P. Berrange } 4403e308f20SDaniel P. Berrange 4413e308f20SDaniel P. Berrange splitkeylen = masterkeylen * slot->stripes; 4423e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 4433e308f20SDaniel P. Berrange possiblekey = g_new0(uint8_t, masterkeylen); 4443e308f20SDaniel P. Berrange 4453e308f20SDaniel P. Berrange /* 4463e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 4473e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 4483e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 4493e308f20SDaniel P. Berrange * the key is correct and validate the results of 4503e308f20SDaniel P. Berrange * decryption later. 4513e308f20SDaniel P. Berrange */ 4523e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(hash, 4533e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 4543e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 4553e308f20SDaniel P. Berrange slot->iterations, 4563e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4573e308f20SDaniel P. Berrange errp) < 0) { 458*57b9f113SDaniel P. Berrangé return -1; 4593e308f20SDaniel P. Berrange } 4603e308f20SDaniel P. Berrange 4613e308f20SDaniel P. Berrange /* 4623e308f20SDaniel P. Berrange * We need to read the master key material from the 4633e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 4643e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 4653e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 4663e308f20SDaniel P. Berrange * then encrypted. 4673e308f20SDaniel P. Berrange */ 4683e308f20SDaniel P. Berrange rv = readfunc(block, 4693e308f20SDaniel P. Berrange slot->key_offset * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 4703e308f20SDaniel P. Berrange splitkey, splitkeylen, 471e4a3507eSDaniel P. Berrange opaque, 47237509233SFam Zheng errp); 4733e308f20SDaniel P. Berrange if (rv < 0) { 474*57b9f113SDaniel P. Berrangé return -1; 4753e308f20SDaniel P. Berrange } 4763e308f20SDaniel P. Berrange 4773e308f20SDaniel P. Berrange 4783e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 4793e308f20SDaniel P. Berrange * the split master key material */ 4803e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(cipheralg, ciphermode, 4813e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4823e308f20SDaniel P. Berrange errp); 4833e308f20SDaniel P. Berrange if (!cipher) { 484*57b9f113SDaniel P. Berrangé return -1; 4853e308f20SDaniel P. Berrange } 4863e308f20SDaniel P. Berrange 4873e308f20SDaniel P. Berrange niv = qcrypto_cipher_get_iv_len(cipheralg, 4883e308f20SDaniel P. Berrange ciphermode); 4893e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(ivalg, 4903e308f20SDaniel P. Berrange ivcipheralg, 4913e308f20SDaniel P. Berrange ivhash, 4923e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4933e308f20SDaniel P. Berrange errp); 4943e308f20SDaniel P. Berrange if (!ivgen) { 495*57b9f113SDaniel P. Berrangé return -1; 4963e308f20SDaniel P. Berrange } 4973e308f20SDaniel P. Berrange 4983e308f20SDaniel P. Berrange 4993e308f20SDaniel P. Berrange /* 5003e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 5013e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 5023e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 5033e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 5043e308f20SDaniel P. Berrange * key crosses a sector boundary. 5053e308f20SDaniel P. Berrange */ 5060270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 5073e308f20SDaniel P. Berrange niv, 5083e308f20SDaniel P. Berrange ivgen, 5093e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 5103e308f20SDaniel P. Berrange 0, 5113e308f20SDaniel P. Berrange splitkey, 5123e308f20SDaniel P. Berrange splitkeylen, 5133e308f20SDaniel P. Berrange errp) < 0) { 514*57b9f113SDaniel P. Berrangé return -1; 5153e308f20SDaniel P. Berrange } 5163e308f20SDaniel P. Berrange 5173e308f20SDaniel P. Berrange /* 5183e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 5193e308f20SDaniel P. Berrange * it back together to get the actual master key. 5203e308f20SDaniel P. Berrange */ 5213e308f20SDaniel P. Berrange if (qcrypto_afsplit_decode(hash, 5223e308f20SDaniel P. Berrange masterkeylen, 5233e308f20SDaniel P. Berrange slot->stripes, 5243e308f20SDaniel P. Berrange splitkey, 5253e308f20SDaniel P. Berrange masterkey, 5263e308f20SDaniel P. Berrange errp) < 0) { 527*57b9f113SDaniel P. Berrangé return -1; 5283e308f20SDaniel P. Berrange } 5293e308f20SDaniel P. Berrange 5303e308f20SDaniel P. Berrange 5313e308f20SDaniel P. Berrange /* 5323e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 5333e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 5343e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 5353e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 5363e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 5373e308f20SDaniel P. Berrange * header 5383e308f20SDaniel P. Berrange */ 5393e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(hash, 5403e308f20SDaniel P. Berrange masterkey, masterkeylen, 5413e308f20SDaniel P. Berrange luks->header.master_key_salt, 5423e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 5433e308f20SDaniel P. Berrange luks->header.master_key_iterations, 5443e308f20SDaniel P. Berrange keydigest, G_N_ELEMENTS(keydigest), 5453e308f20SDaniel P. Berrange errp) < 0) { 546*57b9f113SDaniel P. Berrangé return -1; 5473e308f20SDaniel P. Berrange } 5483e308f20SDaniel P. Berrange 5493e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 5503e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 5513e308f20SDaniel P. Berrange /* Success, we got the right master key */ 552*57b9f113SDaniel P. Berrangé return 1; 5533e308f20SDaniel P. Berrange } 5543e308f20SDaniel P. Berrange 5553e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 5563e308f20SDaniel P. Berrange * tell caller to try another slot */ 557*57b9f113SDaniel P. Berrangé return 0; 5583e308f20SDaniel P. Berrange } 5593e308f20SDaniel P. Berrange 5603e308f20SDaniel P. Berrange 5613e308f20SDaniel P. Berrange /* 5623e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 5633e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 5643e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 5653e308f20SDaniel P. Berrange * 5663e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 5673e308f20SDaniel P. Berrange */ 5683e308f20SDaniel P. Berrange static int 5693e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 5703e308f20SDaniel P. Berrange const char *password, 5713e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg, 5723e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode, 5733e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 5743e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg, 5753e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg, 5763e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash, 5773e308f20SDaniel P. Berrange uint8_t **masterkey, 5783e308f20SDaniel P. Berrange size_t *masterkeylen, 5793e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 5803e308f20SDaniel P. Berrange void *opaque, 5813e308f20SDaniel P. Berrange Error **errp) 5823e308f20SDaniel P. Berrange { 5833e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 5843e308f20SDaniel P. Berrange size_t i; 5853e308f20SDaniel P. Berrange int rv; 5863e308f20SDaniel P. Berrange 5873e308f20SDaniel P. Berrange *masterkey = g_new0(uint8_t, luks->header.key_bytes); 5883e308f20SDaniel P. Berrange *masterkeylen = luks->header.key_bytes; 5893e308f20SDaniel P. Berrange 5903e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 5913e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 5923e308f20SDaniel P. Berrange &luks->header.key_slots[i], 5933e308f20SDaniel P. Berrange password, 5943e308f20SDaniel P. Berrange cipheralg, 5953e308f20SDaniel P. Berrange ciphermode, 5963e308f20SDaniel P. Berrange hash, 5973e308f20SDaniel P. Berrange ivalg, 5983e308f20SDaniel P. Berrange ivcipheralg, 5993e308f20SDaniel P. Berrange ivhash, 6003e308f20SDaniel P. Berrange *masterkey, 6013e308f20SDaniel P. Berrange *masterkeylen, 6023e308f20SDaniel P. Berrange readfunc, 6033e308f20SDaniel P. Berrange opaque, 6043e308f20SDaniel P. Berrange errp); 6053e308f20SDaniel P. Berrange if (rv < 0) { 6063e308f20SDaniel P. Berrange goto error; 6073e308f20SDaniel P. Berrange } 6083e308f20SDaniel P. Berrange if (rv == 1) { 6093e308f20SDaniel P. Berrange return 0; 6103e308f20SDaniel P. Berrange } 6113e308f20SDaniel P. Berrange } 6123e308f20SDaniel P. Berrange 6133e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 6143e308f20SDaniel P. Berrange 6153e308f20SDaniel P. Berrange error: 6163e308f20SDaniel P. Berrange g_free(*masterkey); 6173e308f20SDaniel P. Berrange *masterkey = NULL; 6183e308f20SDaniel P. Berrange *masterkeylen = 0; 6193e308f20SDaniel P. Berrange return -1; 6203e308f20SDaniel P. Berrange } 6213e308f20SDaniel P. Berrange 6223e308f20SDaniel P. Berrange 6233e308f20SDaniel P. Berrange static int 6243e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 6253e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 6261cd9a787SDaniel P. Berrange const char *optprefix, 6273e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 6283e308f20SDaniel P. Berrange void *opaque, 6293e308f20SDaniel P. Berrange unsigned int flags, 630c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 6313e308f20SDaniel P. Berrange Error **errp) 6323e308f20SDaniel P. Berrange { 6333e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 6343e308f20SDaniel P. Berrange Error *local_err = NULL; 6353e308f20SDaniel P. Berrange int ret = 0; 6363e308f20SDaniel P. Berrange size_t i; 6373e308f20SDaniel P. Berrange ssize_t rv; 638*57b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 6393e308f20SDaniel P. Berrange size_t masterkeylen; 6403e308f20SDaniel P. Berrange char *ivgen_name, *ivhash_name; 6413e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode; 6423e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg; 6433e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg; 6443e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg; 6453e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash; 6463e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash; 647*57b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 6483e308f20SDaniel P. Berrange 6493e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 6503e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 6511cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 6521cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 6533e308f20SDaniel P. Berrange return -1; 6543e308f20SDaniel P. Berrange } 6553e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 6563e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 6573e308f20SDaniel P. Berrange if (!password) { 6583e308f20SDaniel P. Berrange return -1; 6593e308f20SDaniel P. Berrange } 6603e308f20SDaniel P. Berrange } 6613e308f20SDaniel P. Berrange 6623e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 6633e308f20SDaniel P. Berrange block->opaque = luks; 6643e308f20SDaniel P. Berrange 6653e308f20SDaniel P. Berrange /* Read the entire LUKS header, minus the key material from 6663e308f20SDaniel P. Berrange * the underlying device */ 667e4a3507eSDaniel P. Berrange rv = readfunc(block, 0, 6683e308f20SDaniel P. Berrange (uint8_t *)&luks->header, 6693e308f20SDaniel P. Berrange sizeof(luks->header), 670e4a3507eSDaniel P. Berrange opaque, 67137509233SFam Zheng errp); 6723e308f20SDaniel P. Berrange if (rv < 0) { 6733e308f20SDaniel P. Berrange ret = rv; 6743e308f20SDaniel P. Berrange goto fail; 6753e308f20SDaniel P. Berrange } 6763e308f20SDaniel P. Berrange 6773e308f20SDaniel P. Berrange /* The header is always stored in big-endian format, so 6783e308f20SDaniel P. Berrange * convert everything to native */ 6793e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 6803e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.payload_offset); 6813e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_bytes); 6823e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 6833e308f20SDaniel P. Berrange 6843e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 6853e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 6863e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 6873e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].key_offset); 6883e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 6893e308f20SDaniel P. Berrange } 6903e308f20SDaniel P. Berrange 6913e308f20SDaniel P. Berrange if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 6923e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 6933e308f20SDaniel P. Berrange error_setg(errp, "Volume is not in LUKS format"); 6943e308f20SDaniel P. Berrange ret = -EINVAL; 6953e308f20SDaniel P. Berrange goto fail; 6963e308f20SDaniel P. Berrange } 6973e308f20SDaniel P. Berrange if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 6983e308f20SDaniel P. Berrange error_setg(errp, "LUKS version %" PRIu32 " is not supported", 6993e308f20SDaniel P. Berrange luks->header.version); 7003e308f20SDaniel P. Berrange ret = -ENOTSUP; 7013e308f20SDaniel P. Berrange goto fail; 7023e308f20SDaniel P. Berrange } 7033e308f20SDaniel P. Berrange 7043e308f20SDaniel P. Berrange /* 7053e308f20SDaniel P. Berrange * The cipher_mode header contains a string that we have 7063e308f20SDaniel P. Berrange * to further parse, of the format 7073e308f20SDaniel P. Berrange * 7083e308f20SDaniel P. Berrange * <cipher-mode>-<iv-generator>[:<iv-hash>] 7093e308f20SDaniel P. Berrange * 7103e308f20SDaniel P. Berrange * eg cbc-essiv:sha256, cbc-plain64 7113e308f20SDaniel P. Berrange */ 7123e308f20SDaniel P. Berrange ivgen_name = strchr(luks->header.cipher_mode, '-'); 7133e308f20SDaniel P. Berrange if (!ivgen_name) { 7143e308f20SDaniel P. Berrange ret = -EINVAL; 7153e308f20SDaniel P. Berrange error_setg(errp, "Unexpected cipher mode string format %s", 7163e308f20SDaniel P. Berrange luks->header.cipher_mode); 7173e308f20SDaniel P. Berrange goto fail; 7183e308f20SDaniel P. Berrange } 7193e308f20SDaniel P. Berrange *ivgen_name = '\0'; 7203e308f20SDaniel P. Berrange ivgen_name++; 7213e308f20SDaniel P. Berrange 7223e308f20SDaniel P. Berrange ivhash_name = strchr(ivgen_name, ':'); 7233e308f20SDaniel P. Berrange if (!ivhash_name) { 7243e308f20SDaniel P. Berrange ivhash = 0; 7253e308f20SDaniel P. Berrange } else { 7263e308f20SDaniel P. Berrange *ivhash_name = '\0'; 7273e308f20SDaniel P. Berrange ivhash_name++; 7283e308f20SDaniel P. Berrange 7293e308f20SDaniel P. Berrange ivhash = qcrypto_block_luks_hash_name_lookup(ivhash_name, 7303e308f20SDaniel P. Berrange &local_err); 7313e308f20SDaniel P. Berrange if (local_err) { 7323e308f20SDaniel P. Berrange ret = -ENOTSUP; 7333e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7343e308f20SDaniel P. Berrange goto fail; 7353e308f20SDaniel P. Berrange } 7363e308f20SDaniel P. Berrange } 7373e308f20SDaniel P. Berrange 7383e308f20SDaniel P. Berrange ciphermode = qcrypto_block_luks_cipher_mode_lookup(luks->header.cipher_mode, 7393e308f20SDaniel P. Berrange &local_err); 7403e308f20SDaniel P. Berrange if (local_err) { 7413e308f20SDaniel P. Berrange ret = -ENOTSUP; 7423e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7433e308f20SDaniel P. Berrange goto fail; 7443e308f20SDaniel P. Berrange } 7453e308f20SDaniel P. Berrange 7463e308f20SDaniel P. Berrange cipheralg = qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 7473e308f20SDaniel P. Berrange ciphermode, 7483e308f20SDaniel P. Berrange luks->header.key_bytes, 7493e308f20SDaniel P. Berrange &local_err); 7503e308f20SDaniel P. Berrange if (local_err) { 7513e308f20SDaniel P. Berrange ret = -ENOTSUP; 7523e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7533e308f20SDaniel P. Berrange goto fail; 7543e308f20SDaniel P. Berrange } 7553e308f20SDaniel P. Berrange 7563e308f20SDaniel P. Berrange hash = qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 7573e308f20SDaniel P. Berrange &local_err); 7583e308f20SDaniel P. Berrange if (local_err) { 7593e308f20SDaniel P. Berrange ret = -ENOTSUP; 7603e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7613e308f20SDaniel P. Berrange goto fail; 7623e308f20SDaniel P. Berrange } 7633e308f20SDaniel P. Berrange 7643e308f20SDaniel P. Berrange ivalg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 7653e308f20SDaniel P. Berrange &local_err); 7663e308f20SDaniel P. Berrange if (local_err) { 7673e308f20SDaniel P. Berrange ret = -ENOTSUP; 7683e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7693e308f20SDaniel P. Berrange goto fail; 7703e308f20SDaniel P. Berrange } 7713e308f20SDaniel P. Berrange 7723e308f20SDaniel P. Berrange if (ivalg == QCRYPTO_IVGEN_ALG_ESSIV) { 7738b7cdba3SDaniel P. Berrange if (!ivhash_name) { 7748b7cdba3SDaniel P. Berrange ret = -EINVAL; 7758b7cdba3SDaniel P. Berrange error_setg(errp, "Missing IV generator hash specification"); 7768b7cdba3SDaniel P. Berrange goto fail; 7778b7cdba3SDaniel P. Berrange } 7783e308f20SDaniel P. Berrange ivcipheralg = qcrypto_block_luks_essiv_cipher(cipheralg, 7793e308f20SDaniel P. Berrange ivhash, 7803e308f20SDaniel P. Berrange &local_err); 7813e308f20SDaniel P. Berrange if (local_err) { 7823e308f20SDaniel P. Berrange ret = -ENOTSUP; 7833e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7843e308f20SDaniel P. Berrange goto fail; 7853e308f20SDaniel P. Berrange } 7863e308f20SDaniel P. Berrange } else { 7878b7cdba3SDaniel P. Berrange /* Note we parsed the ivhash_name earlier in the cipher_mode 7888b7cdba3SDaniel P. Berrange * spec string even with plain/plain64 ivgens, but we 7898b7cdba3SDaniel P. Berrange * will ignore it, since it is irrelevant for these ivgens. 7908b7cdba3SDaniel P. Berrange * This is for compat with dm-crypt which will silently 7918b7cdba3SDaniel P. Berrange * ignore hash names with these ivgens rather than report 7928b7cdba3SDaniel P. Berrange * an error about the invalid usage 7938b7cdba3SDaniel P. Berrange */ 7943e308f20SDaniel P. Berrange ivcipheralg = cipheralg; 7953e308f20SDaniel P. Berrange } 7963e308f20SDaniel P. Berrange 7973e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 7983e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 7993e308f20SDaniel P. Berrange * and unlock the master key from that slot. 8003e308f20SDaniel P. Berrange */ 8013e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 8023e308f20SDaniel P. Berrange password, 8033e308f20SDaniel P. Berrange cipheralg, ciphermode, 8043e308f20SDaniel P. Berrange hash, 8053e308f20SDaniel P. Berrange ivalg, 8063e308f20SDaniel P. Berrange ivcipheralg, 8073e308f20SDaniel P. Berrange ivhash, 8083e308f20SDaniel P. Berrange &masterkey, &masterkeylen, 8093e308f20SDaniel P. Berrange readfunc, opaque, 8103e308f20SDaniel P. Berrange errp) < 0) { 8113e308f20SDaniel P. Berrange ret = -EACCES; 8123e308f20SDaniel P. Berrange goto fail; 8133e308f20SDaniel P. Berrange } 8143e308f20SDaniel P. Berrange 8153e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 8163e308f20SDaniel P. Berrange * block device payload decryption objects 8173e308f20SDaniel P. Berrange */ 8183e308f20SDaniel P. Berrange block->kdfhash = hash; 8193e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(cipheralg, 8203e308f20SDaniel P. Berrange ciphermode); 8213e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(ivalg, 8223e308f20SDaniel P. Berrange ivcipheralg, 8233e308f20SDaniel P. Berrange ivhash, 8243e308f20SDaniel P. Berrange masterkey, masterkeylen, 8253e308f20SDaniel P. Berrange errp); 8263e308f20SDaniel P. Berrange if (!block->ivgen) { 8273e308f20SDaniel P. Berrange ret = -ENOTSUP; 8283e308f20SDaniel P. Berrange goto fail; 8293e308f20SDaniel P. Berrange } 8303e308f20SDaniel P. Berrange 831c972fa12SVladimir Sementsov-Ogievskiy ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode, 832c972fa12SVladimir Sementsov-Ogievskiy masterkey, masterkeylen, n_threads, 8333e308f20SDaniel P. Berrange errp); 834c972fa12SVladimir Sementsov-Ogievskiy if (ret < 0) { 8353e308f20SDaniel P. Berrange ret = -ENOTSUP; 8363e308f20SDaniel P. Berrange goto fail; 8373e308f20SDaniel P. Berrange } 8383e308f20SDaniel P. Berrange } 8393e308f20SDaniel P. Berrange 840850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 8413e308f20SDaniel P. Berrange block->payload_offset = luks->header.payload_offset * 842850f49deSDaniel P. Berrange block->sector_size; 8433e308f20SDaniel P. Berrange 84440c85028SDaniel P. Berrange luks->cipher_alg = cipheralg; 84540c85028SDaniel P. Berrange luks->cipher_mode = ciphermode; 84640c85028SDaniel P. Berrange luks->ivgen_alg = ivalg; 84740c85028SDaniel P. Berrange luks->ivgen_hash_alg = ivhash; 84840c85028SDaniel P. Berrange luks->hash_alg = hash; 84940c85028SDaniel P. Berrange 8503e308f20SDaniel P. Berrange return 0; 8513e308f20SDaniel P. Berrange 8523e308f20SDaniel P. Berrange fail: 853c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 8543e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 8553e308f20SDaniel P. Berrange g_free(luks); 8563e308f20SDaniel P. Berrange return ret; 8573e308f20SDaniel P. Berrange } 8583e308f20SDaniel P. Berrange 8593e308f20SDaniel P. Berrange 8602ef950f9SFam Zheng static void 8612ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 8623e308f20SDaniel P. Berrange { 8632ef950f9SFam Zheng QemuUUID uuid; 8642ef950f9SFam Zheng qemu_uuid_generate(&uuid); 8652ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 8663e308f20SDaniel P. Berrange } 8673e308f20SDaniel P. Berrange 8683e308f20SDaniel P. Berrange static int 8693e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 8703e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 8711cd9a787SDaniel P. Berrange const char *optprefix, 8723e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 8733e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 8743e308f20SDaniel P. Berrange void *opaque, 8753e308f20SDaniel P. Berrange Error **errp) 8763e308f20SDaniel P. Berrange { 8773e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 8783e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 8793e308f20SDaniel P. Berrange Error *local_err = NULL; 880*57b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 881*57b9f113SDaniel P. Berrangé g_autofree uint8_t *slotkey = NULL; 882*57b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 8833e308f20SDaniel P. Berrange size_t splitkeylen = 0; 8843e308f20SDaniel P. Berrange size_t i; 885*57b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 886*57b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 887*57b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 8883e308f20SDaniel P. Berrange const char *cipher_alg; 8893e308f20SDaniel P. Berrange const char *cipher_mode; 8903e308f20SDaniel P. Berrange const char *ivgen_alg; 8913e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 8923e308f20SDaniel P. Berrange const char *hash_alg; 893*57b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 8943e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg = 0; 89559b060beSDaniel P. Berrange uint64_t iters; 8963e308f20SDaniel P. Berrange 8973e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 8983bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 8992ab66cd5SDaniel P. Berrange luks_opts.iter_time = 2000; 9003bd18890SDaniel P. Berrange } 9013e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 9023e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 9033e308f20SDaniel P. Berrange } 9043e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 9053e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 9063e308f20SDaniel P. Berrange } 9073e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 9083e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 9093e308f20SDaniel P. Berrange } 9103e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 9113e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 9123e308f20SDaniel P. Berrange } 9138b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9148b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 9158b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 9168b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 9178b7cdba3SDaniel P. Berrange } 9188b7cdba3SDaniel P. Berrange } 9198b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 9208b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 9218b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 9223e308f20SDaniel P. Berrange 9233e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 9241cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 9251cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 9263e308f20SDaniel P. Berrange return -1; 9273e308f20SDaniel P. Berrange } 9283e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 9293e308f20SDaniel P. Berrange if (!password) { 9303e308f20SDaniel P. Berrange return -1; 9313e308f20SDaniel P. Berrange } 9323e308f20SDaniel P. Berrange 9333e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 9343e308f20SDaniel P. Berrange block->opaque = luks; 9353e308f20SDaniel P. Berrange 9363e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 9373e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 9383e308f20SDaniel P. Berrange 9393e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 9403e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 9413e308f20SDaniel P. Berrange * it out to disk 9423e308f20SDaniel P. Berrange */ 9433e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 9442ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 9453e308f20SDaniel P. Berrange 9463e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 9473e308f20SDaniel P. Berrange errp); 9483e308f20SDaniel P. Berrange if (!cipher_alg) { 9493e308f20SDaniel P. Berrange goto error; 9503e308f20SDaniel P. Berrange } 9513e308f20SDaniel P. Berrange 952977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 953977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 9543e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 955977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 9563e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 9573e308f20SDaniel P. Berrange ivgen_hash_alg); 9583e308f20SDaniel P. Berrange } else { 9593e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 9603e308f20SDaniel P. Berrange } 961977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 9623e308f20SDaniel P. Berrange 9633e308f20SDaniel P. Berrange 9643e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 9653e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 9663e308f20SDaniel P. Berrange cipher_alg); 9673e308f20SDaniel P. Berrange goto error; 9683e308f20SDaniel P. Berrange } 9693e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 9703e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 9713e308f20SDaniel P. Berrange cipher_mode_spec); 9723e308f20SDaniel P. Berrange goto error; 9733e308f20SDaniel P. Berrange } 9743e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 9753e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 9763e308f20SDaniel P. Berrange hash_alg); 9773e308f20SDaniel P. Berrange goto error; 9783e308f20SDaniel P. Berrange } 9793e308f20SDaniel P. Berrange 9803e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9813e308f20SDaniel P. Berrange ivcipheralg = qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 9823e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 9833e308f20SDaniel P. Berrange &local_err); 9843e308f20SDaniel P. Berrange if (local_err) { 9853e308f20SDaniel P. Berrange error_propagate(errp, local_err); 9863e308f20SDaniel P. Berrange goto error; 9873e308f20SDaniel P. Berrange } 9883e308f20SDaniel P. Berrange } else { 9893e308f20SDaniel P. Berrange ivcipheralg = luks_opts.cipher_alg; 9903e308f20SDaniel P. Berrange } 9913e308f20SDaniel P. Berrange 9923e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 9933e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 9943e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 9953e308f20SDaniel P. Berrange 9963e308f20SDaniel P. Berrange luks->header.key_bytes = qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 9973e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 9983e308f20SDaniel P. Berrange luks->header.key_bytes *= 2; 9993e308f20SDaniel P. Berrange } 10003e308f20SDaniel P. Berrange 10013e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 10023e308f20SDaniel P. Berrange * with PBKDF later 10033e308f20SDaniel P. Berrange */ 10043e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 10053e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10063e308f20SDaniel P. Berrange errp) < 0) { 10073e308f20SDaniel P. Berrange goto error; 10083e308f20SDaniel P. Berrange } 10093e308f20SDaniel P. Berrange 10103e308f20SDaniel P. Berrange /* Generate random master key */ 10113e308f20SDaniel P. Berrange masterkey = g_new0(uint8_t, luks->header.key_bytes); 10123e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 10133e308f20SDaniel P. Berrange luks->header.key_bytes, errp) < 0) { 10143e308f20SDaniel P. Berrange goto error; 10153e308f20SDaniel P. Berrange } 10163e308f20SDaniel P. Berrange 10173e308f20SDaniel P. Berrange 10183e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1019c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1020c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1021c972fa12SVladimir Sementsov-Ogievskiy luks->header.key_bytes, 1, errp) < 0) { 10223e308f20SDaniel P. Berrange goto error; 10233e308f20SDaniel P. Berrange } 10243e308f20SDaniel P. Berrange 10253e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 10263e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 10273e308f20SDaniel P. Berrange luks_opts.cipher_mode); 10283e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 10293e308f20SDaniel P. Berrange ivcipheralg, 10303e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 10313e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10323e308f20SDaniel P. Berrange errp); 10333e308f20SDaniel P. Berrange 10343e308f20SDaniel P. Berrange if (!block->ivgen) { 10353e308f20SDaniel P. Berrange goto error; 10363e308f20SDaniel P. Berrange } 10373e308f20SDaniel P. Berrange 10383e308f20SDaniel P. Berrange 10393e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 10403e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 10413e308f20SDaniel P. Berrange */ 104259b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 10433e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10443e308f20SDaniel P. Berrange luks->header.master_key_salt, 10453e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1046e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 10473e308f20SDaniel P. Berrange &local_err); 10483e308f20SDaniel P. Berrange if (local_err) { 10493e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10503e308f20SDaniel P. Berrange goto error; 10513e308f20SDaniel P. Berrange } 10523e308f20SDaniel P. Berrange 10533bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 10543bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 10553bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 10563bd18890SDaniel P. Berrange (unsigned long long)iters); 10573bd18890SDaniel P. Berrange goto error; 10583bd18890SDaniel P. Berrange } 10593bd18890SDaniel P. Berrange 10603bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 10613bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 10623bd18890SDaniel P. Berrange 10633e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 10643e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 10653e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 10663e308f20SDaniel P. Berrange * in total time to check all keys */ 106759b060beSDaniel P. Berrange iters /= 8; 106859b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 106959b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 107059b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 107159b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 107259b060beSDaniel P. Berrange goto error; 107359b060beSDaniel P. Berrange } 107459b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 107559b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 10763e308f20SDaniel P. Berrange 10773e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 10783e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 10793e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 10803e308f20SDaniel P. Berrange * valid master key 10813e308f20SDaniel P. Berrange */ 10823e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 10833e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10843e308f20SDaniel P. Berrange luks->header.master_key_salt, 10853e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10863e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10873e308f20SDaniel P. Berrange luks->header.master_key_digest, 10883e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 10893e308f20SDaniel P. Berrange errp) < 0) { 10903e308f20SDaniel P. Berrange goto error; 10913e308f20SDaniel P. Berrange } 10923e308f20SDaniel P. Berrange 10933e308f20SDaniel P. Berrange 10943e308f20SDaniel P. Berrange /* Although LUKS has multiple key slots, we're just going 10953e308f20SDaniel P. Berrange * to use the first key slot */ 10963e308f20SDaniel P. Berrange splitkeylen = luks->header.key_bytes * QCRYPTO_BLOCK_LUKS_STRIPES; 10973e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10983e308f20SDaniel P. Berrange luks->header.key_slots[i].active = i == 0 ? 10993e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED : 11003e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 11013e308f20SDaniel P. Berrange luks->header.key_slots[i].stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 11023e308f20SDaniel P. Berrange 11033e308f20SDaniel P. Berrange /* This calculation doesn't match that shown in the spec, 11043e308f20SDaniel P. Berrange * but instead follows the cryptsetup implementation. 11053e308f20SDaniel P. Berrange */ 11063e308f20SDaniel P. Berrange luks->header.key_slots[i].key_offset = 11073e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11083e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1109207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 11103e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11113e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i); 11123e308f20SDaniel P. Berrange } 11133e308f20SDaniel P. Berrange 11143e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.key_slots[0].salt, 11153e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11163e308f20SDaniel P. Berrange errp) < 0) { 11173e308f20SDaniel P. Berrange goto error; 11183e308f20SDaniel P. Berrange } 11193e308f20SDaniel P. Berrange 11203e308f20SDaniel P. Berrange /* Again we determine how many iterations are required to 11213e308f20SDaniel P. Berrange * hash the user password while consuming 1 second of compute 11223e308f20SDaniel P. Berrange * time */ 112359b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 11243e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11253e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1127e74aabcfSDaniel P. Berrange luks->header.key_bytes, 11283e308f20SDaniel P. Berrange &local_err); 11293e308f20SDaniel P. Berrange if (local_err) { 11303e308f20SDaniel P. Berrange error_propagate(errp, local_err); 11313e308f20SDaniel P. Berrange goto error; 11323e308f20SDaniel P. Berrange } 11333bd18890SDaniel P. Berrange 11343bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 11353bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 11363bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 11373bd18890SDaniel P. Berrange (unsigned long long)iters); 11383bd18890SDaniel P. Berrange goto error; 11393bd18890SDaniel P. Berrange } 11403bd18890SDaniel P. Berrange 11413bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 11423bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 11433bd18890SDaniel P. Berrange 114459b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 114559b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 114659b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 114759b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 114859b060beSDaniel P. Berrange goto error; 114959b060beSDaniel P. Berrange } 115059b060beSDaniel P. Berrange 115159b060beSDaniel P. Berrange luks->header.key_slots[0].iterations = 115259b060beSDaniel P. Berrange MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 11533e308f20SDaniel P. Berrange 11543e308f20SDaniel P. Berrange 11553e308f20SDaniel P. Berrange /* Generate a key that we'll use to encrypt the master 11563e308f20SDaniel P. Berrange * key, from the user's password 11573e308f20SDaniel P. Berrange */ 11583e308f20SDaniel P. Berrange slotkey = g_new0(uint8_t, luks->header.key_bytes); 11593e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 11603e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11613e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11623e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11633e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations, 11643e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11653e308f20SDaniel P. Berrange errp) < 0) { 11663e308f20SDaniel P. Berrange goto error; 11673e308f20SDaniel P. Berrange } 11683e308f20SDaniel P. Berrange 11693e308f20SDaniel P. Berrange 11703e308f20SDaniel P. Berrange /* Setup the encryption objects needed to encrypt the 11713e308f20SDaniel P. Berrange * master key material 11723e308f20SDaniel P. Berrange */ 11733e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(luks_opts.cipher_alg, 11743e308f20SDaniel P. Berrange luks_opts.cipher_mode, 11753e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11763e308f20SDaniel P. Berrange errp); 11773e308f20SDaniel P. Berrange if (!cipher) { 11783e308f20SDaniel P. Berrange goto error; 11793e308f20SDaniel P. Berrange } 11803e308f20SDaniel P. Berrange 11813e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 11823e308f20SDaniel P. Berrange ivcipheralg, 11833e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 11843e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11853e308f20SDaniel P. Berrange errp); 11863e308f20SDaniel P. Berrange if (!ivgen) { 11873e308f20SDaniel P. Berrange goto error; 11883e308f20SDaniel P. Berrange } 11893e308f20SDaniel P. Berrange 11903e308f20SDaniel P. Berrange /* Before storing the master key, we need to vastly 11913e308f20SDaniel P. Berrange * increase its size, as protection against forensic 11923e308f20SDaniel P. Berrange * disk data recovery */ 11933e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 11943e308f20SDaniel P. Berrange 11953e308f20SDaniel P. Berrange if (qcrypto_afsplit_encode(luks_opts.hash_alg, 11963e308f20SDaniel P. Berrange luks->header.key_bytes, 11973e308f20SDaniel P. Berrange luks->header.key_slots[0].stripes, 11983e308f20SDaniel P. Berrange masterkey, 11993e308f20SDaniel P. Berrange splitkey, 12003e308f20SDaniel P. Berrange errp) < 0) { 12013e308f20SDaniel P. Berrange goto error; 12023e308f20SDaniel P. Berrange } 12033e308f20SDaniel P. Berrange 12043e308f20SDaniel P. Berrange /* Now we encrypt the split master key with the key generated 12053e308f20SDaniel P. Berrange * from the user's password, before storing it */ 12060270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 12073e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12083e308f20SDaniel P. Berrange 0, 12093e308f20SDaniel P. Berrange splitkey, 12103e308f20SDaniel P. Berrange splitkeylen, 12113e308f20SDaniel P. Berrange errp) < 0) { 12123e308f20SDaniel P. Berrange goto error; 12133e308f20SDaniel P. Berrange } 12143e308f20SDaniel P. Berrange 12153e308f20SDaniel P. Berrange 12163e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 12173e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 12183e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 12193e308f20SDaniel P. Berrange * to the nearest sector */ 12203e308f20SDaniel P. Berrange luks->header.payload_offset = 12213e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12223e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1223207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 12243e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12253e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * 12263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 12273e308f20SDaniel P. Berrange 1228850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 12293e308f20SDaniel P. Berrange block->payload_offset = luks->header.payload_offset * 1230850f49deSDaniel P. Berrange block->sector_size; 12313e308f20SDaniel P. Berrange 12323e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1233e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 12343e308f20SDaniel P. Berrange if (local_err) { 12353e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12363e308f20SDaniel P. Berrange goto error; 12373e308f20SDaniel P. Berrange } 12383e308f20SDaniel P. Berrange 12393e308f20SDaniel P. Berrange /* Everything on disk uses Big Endian, so flip header fields 12403e308f20SDaniel P. Berrange * before writing them */ 12413e308f20SDaniel P. Berrange cpu_to_be16s(&luks->header.version); 12423e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.payload_offset); 12433e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_bytes); 12443e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.master_key_iterations); 12453e308f20SDaniel P. Berrange 12463e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12473e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].active); 12483e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].iterations); 12493e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].key_offset); 12503e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].stripes); 12513e308f20SDaniel P. Berrange } 12523e308f20SDaniel P. Berrange 12533e308f20SDaniel P. Berrange 12543e308f20SDaniel P. Berrange /* Write out the partition header and key slot headers */ 1255e4a3507eSDaniel P. Berrange writefunc(block, 0, 12563e308f20SDaniel P. Berrange (const uint8_t *)&luks->header, 12573e308f20SDaniel P. Berrange sizeof(luks->header), 1258e4a3507eSDaniel P. Berrange opaque, 125937509233SFam Zheng &local_err); 12603e308f20SDaniel P. Berrange 12613e308f20SDaniel P. Berrange /* Delay checking local_err until we've byte-swapped */ 12623e308f20SDaniel P. Berrange 12633e308f20SDaniel P. Berrange /* Byte swap the header back to native, in case we need 12643e308f20SDaniel P. Berrange * to read it again later */ 12653e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 12663e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.payload_offset); 12673e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_bytes); 12683e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 12693e308f20SDaniel P. Berrange 12703e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12713e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 12723e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 12733e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].key_offset); 12743e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 12753e308f20SDaniel P. Berrange } 12763e308f20SDaniel P. Berrange 12773e308f20SDaniel P. Berrange if (local_err) { 12783e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12793e308f20SDaniel P. Berrange goto error; 12803e308f20SDaniel P. Berrange } 12813e308f20SDaniel P. Berrange 12823e308f20SDaniel P. Berrange /* Write out the master key material, starting at the 12833e308f20SDaniel P. Berrange * sector immediately following the partition header. */ 1284e4a3507eSDaniel P. Berrange if (writefunc(block, 12853e308f20SDaniel P. Berrange luks->header.key_slots[0].key_offset * 12863e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12873e308f20SDaniel P. Berrange splitkey, splitkeylen, 1288e4a3507eSDaniel P. Berrange opaque, 128937509233SFam Zheng errp) != splitkeylen) { 12903e308f20SDaniel P. Berrange goto error; 12913e308f20SDaniel P. Berrange } 12923e308f20SDaniel P. Berrange 129340c85028SDaniel P. Berrange luks->cipher_alg = luks_opts.cipher_alg; 129440c85028SDaniel P. Berrange luks->cipher_mode = luks_opts.cipher_mode; 129540c85028SDaniel P. Berrange luks->ivgen_alg = luks_opts.ivgen_alg; 129640c85028SDaniel P. Berrange luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 129740c85028SDaniel P. Berrange luks->hash_alg = luks_opts.hash_alg; 129840c85028SDaniel P. Berrange 12993e308f20SDaniel P. Berrange memset(masterkey, 0, luks->header.key_bytes); 13003e308f20SDaniel P. Berrange memset(slotkey, 0, luks->header.key_bytes); 13013e308f20SDaniel P. Berrange 13023e308f20SDaniel P. Berrange return 0; 13033e308f20SDaniel P. Berrange 13043e308f20SDaniel P. Berrange error: 13053e308f20SDaniel P. Berrange if (masterkey) { 13063e308f20SDaniel P. Berrange memset(masterkey, 0, luks->header.key_bytes); 13073e308f20SDaniel P. Berrange } 13083e308f20SDaniel P. Berrange if (slotkey) { 13093e308f20SDaniel P. Berrange memset(slotkey, 0, luks->header.key_bytes); 13103e308f20SDaniel P. Berrange } 13113e308f20SDaniel P. Berrange 1312c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1313b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1314b640adcaSVladimir Sementsov-Ogievskiy 13153e308f20SDaniel P. Berrange g_free(luks); 13163e308f20SDaniel P. Berrange return -1; 13173e308f20SDaniel P. Berrange } 13183e308f20SDaniel P. Berrange 13193e308f20SDaniel P. Berrange 132040c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 132140c85028SDaniel P. Berrange QCryptoBlockInfo *info, 132240c85028SDaniel P. Berrange Error **errp) 132340c85028SDaniel P. Berrange { 132440c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 132540c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 132640c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlotList *slots = NULL, **prev = &info->u.luks.slots; 132740c85028SDaniel P. Berrange size_t i; 132840c85028SDaniel P. Berrange 132940c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 133040c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 133140c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 133240c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 133340c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 133440c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 133540c85028SDaniel P. Berrange } 133640c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 133740c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 133840c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 133940c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 134040c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 134140c85028SDaniel P. Berrange 134240c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 134340c85028SDaniel P. Berrange slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1); 134440c85028SDaniel P. Berrange *prev = slots; 134540c85028SDaniel P. Berrange 134640c85028SDaniel P. Berrange slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 134740c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 134840c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 134940c85028SDaniel P. Berrange slot->key_offset = luks->header.key_slots[i].key_offset 135040c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 135140c85028SDaniel P. Berrange if (slot->active) { 135240c85028SDaniel P. Berrange slot->has_iters = true; 135340c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 135440c85028SDaniel P. Berrange slot->has_stripes = true; 135540c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 135640c85028SDaniel P. Berrange } 135740c85028SDaniel P. Berrange 135840c85028SDaniel P. Berrange prev = &slots->next; 135940c85028SDaniel P. Berrange } 136040c85028SDaniel P. Berrange 136140c85028SDaniel P. Berrange return 0; 136240c85028SDaniel P. Berrange } 136340c85028SDaniel P. Berrange 136440c85028SDaniel P. Berrange 13653e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 13663e308f20SDaniel P. Berrange { 13673e308f20SDaniel P. Berrange g_free(block->opaque); 13683e308f20SDaniel P. Berrange } 13693e308f20SDaniel P. Berrange 13703e308f20SDaniel P. Berrange 13713e308f20SDaniel P. Berrange static int 13723e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 13734609742aSDaniel P. Berrange uint64_t offset, 13743e308f20SDaniel P. Berrange uint8_t *buf, 13753e308f20SDaniel P. Berrange size_t len, 13763e308f20SDaniel P. Berrange Error **errp) 13773e308f20SDaniel P. Berrange { 13784609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13794609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13800f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 13813e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13824609742aSDaniel P. Berrange offset, buf, len, errp); 13833e308f20SDaniel P. Berrange } 13843e308f20SDaniel P. Berrange 13853e308f20SDaniel P. Berrange 13863e308f20SDaniel P. Berrange static int 13873e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 13884609742aSDaniel P. Berrange uint64_t offset, 13893e308f20SDaniel P. Berrange uint8_t *buf, 13903e308f20SDaniel P. Berrange size_t len, 13913e308f20SDaniel P. Berrange Error **errp) 13923e308f20SDaniel P. Berrange { 13934609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13944609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 13950f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 13963e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13974609742aSDaniel P. Berrange offset, buf, len, errp); 13983e308f20SDaniel P. Berrange } 13993e308f20SDaniel P. Berrange 14003e308f20SDaniel P. Berrange 14013e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 14023e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 14033e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 140440c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 14053e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 14063e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 14073e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 14083e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 14093e308f20SDaniel P. Berrange }; 1410