13e308f20SDaniel P. Berrange /* 23e308f20SDaniel P. Berrange * QEMU Crypto block device encryption LUKS format 33e308f20SDaniel P. Berrange * 43e308f20SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 53e308f20SDaniel P. Berrange * 63e308f20SDaniel P. Berrange * This library is free software; you can redistribute it and/or 73e308f20SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 83e308f20SDaniel P. Berrange * License as published by the Free Software Foundation; either 93e308f20SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 103e308f20SDaniel P. Berrange * 113e308f20SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 123e308f20SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 133e308f20SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143e308f20SDaniel P. Berrange * Lesser General Public License for more details. 153e308f20SDaniel P. Berrange * 163e308f20SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 173e308f20SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 183e308f20SDaniel P. Berrange * 193e308f20SDaniel P. Berrange */ 203e308f20SDaniel P. Berrange 213e308f20SDaniel P. Berrange #include "qemu/osdep.h" 22da34e65cSMarkus Armbruster #include "qapi/error.h" 2358369e22SPaolo Bonzini #include "qemu/bswap.h" 243e308f20SDaniel P. Berrange 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; 1493e308f20SDaniel P. Berrange } QEMU_PACKED; 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]; 1943e308f20SDaniel P. Berrange } QEMU_PACKED; 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; 4283e308f20SDaniel P. Berrange uint8_t *splitkey; 4293e308f20SDaniel P. Berrange size_t splitkeylen; 4303e308f20SDaniel P. Berrange uint8_t *possiblekey; 4313e308f20SDaniel P. Berrange int ret = -1; 4323e308f20SDaniel P. Berrange ssize_t rv; 4333e308f20SDaniel P. Berrange QCryptoCipher *cipher = NULL; 4343e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 4353e308f20SDaniel P. Berrange QCryptoIVGen *ivgen = NULL; 4363e308f20SDaniel P. Berrange size_t niv; 4373e308f20SDaniel P. Berrange 4383e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 4393e308f20SDaniel P. Berrange return 0; 4403e308f20SDaniel P. Berrange } 4413e308f20SDaniel P. Berrange 4423e308f20SDaniel P. Berrange splitkeylen = masterkeylen * slot->stripes; 4433e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 4443e308f20SDaniel P. Berrange possiblekey = g_new0(uint8_t, masterkeylen); 4453e308f20SDaniel P. Berrange 4463e308f20SDaniel P. Berrange /* 4473e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 4483e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 4493e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 4503e308f20SDaniel P. Berrange * the key is correct and validate the results of 4513e308f20SDaniel P. Berrange * decryption later. 4523e308f20SDaniel P. Berrange */ 4533e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(hash, 4543e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 4553e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 4563e308f20SDaniel P. Berrange slot->iterations, 4573e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4583e308f20SDaniel P. Berrange errp) < 0) { 4593e308f20SDaniel P. Berrange goto cleanup; 4603e308f20SDaniel P. Berrange } 4613e308f20SDaniel P. Berrange 4623e308f20SDaniel P. Berrange /* 4633e308f20SDaniel P. Berrange * We need to read the master key material from the 4643e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 4653e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 4663e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 4673e308f20SDaniel P. Berrange * then encrypted. 4683e308f20SDaniel P. Berrange */ 4693e308f20SDaniel P. Berrange rv = readfunc(block, 4703e308f20SDaniel P. Berrange slot->key_offset * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 4713e308f20SDaniel P. Berrange splitkey, splitkeylen, 472e4a3507eSDaniel P. Berrange opaque, 47337509233SFam Zheng errp); 4743e308f20SDaniel P. Berrange if (rv < 0) { 4753e308f20SDaniel P. Berrange goto cleanup; 4763e308f20SDaniel P. Berrange } 4773e308f20SDaniel P. Berrange 4783e308f20SDaniel P. Berrange 4793e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 4803e308f20SDaniel P. Berrange * the split master key material */ 4813e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(cipheralg, ciphermode, 4823e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4833e308f20SDaniel P. Berrange errp); 4843e308f20SDaniel P. Berrange if (!cipher) { 4853e308f20SDaniel P. Berrange goto cleanup; 4863e308f20SDaniel P. Berrange } 4873e308f20SDaniel P. Berrange 4883e308f20SDaniel P. Berrange niv = qcrypto_cipher_get_iv_len(cipheralg, 4893e308f20SDaniel P. Berrange ciphermode); 4903e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(ivalg, 4913e308f20SDaniel P. Berrange ivcipheralg, 4923e308f20SDaniel P. Berrange ivhash, 4933e308f20SDaniel P. Berrange possiblekey, masterkeylen, 4943e308f20SDaniel P. Berrange errp); 4953e308f20SDaniel P. Berrange if (!ivgen) { 4963e308f20SDaniel P. Berrange goto cleanup; 4973e308f20SDaniel P. Berrange } 4983e308f20SDaniel P. Berrange 4993e308f20SDaniel P. Berrange 5003e308f20SDaniel P. Berrange /* 5013e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 5023e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 5033e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 5043e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 5053e308f20SDaniel P. Berrange * key crosses a sector boundary. 5063e308f20SDaniel P. Berrange */ 5070270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 5083e308f20SDaniel P. Berrange niv, 5093e308f20SDaniel P. Berrange ivgen, 5103e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 5113e308f20SDaniel P. Berrange 0, 5123e308f20SDaniel P. Berrange splitkey, 5133e308f20SDaniel P. Berrange splitkeylen, 5143e308f20SDaniel P. Berrange errp) < 0) { 5153e308f20SDaniel P. Berrange goto cleanup; 5163e308f20SDaniel P. Berrange } 5173e308f20SDaniel P. Berrange 5183e308f20SDaniel P. Berrange /* 5193e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 5203e308f20SDaniel P. Berrange * it back together to get the actual master key. 5213e308f20SDaniel P. Berrange */ 5223e308f20SDaniel P. Berrange if (qcrypto_afsplit_decode(hash, 5233e308f20SDaniel P. Berrange masterkeylen, 5243e308f20SDaniel P. Berrange slot->stripes, 5253e308f20SDaniel P. Berrange splitkey, 5263e308f20SDaniel P. Berrange masterkey, 5273e308f20SDaniel P. Berrange errp) < 0) { 5283e308f20SDaniel P. Berrange goto cleanup; 5293e308f20SDaniel P. Berrange } 5303e308f20SDaniel P. Berrange 5313e308f20SDaniel P. Berrange 5323e308f20SDaniel P. Berrange /* 5333e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 5343e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 5353e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 5363e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 5373e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 5383e308f20SDaniel P. Berrange * header 5393e308f20SDaniel P. Berrange */ 5403e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(hash, 5413e308f20SDaniel P. Berrange masterkey, masterkeylen, 5423e308f20SDaniel P. Berrange luks->header.master_key_salt, 5433e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 5443e308f20SDaniel P. Berrange luks->header.master_key_iterations, 5453e308f20SDaniel P. Berrange keydigest, G_N_ELEMENTS(keydigest), 5463e308f20SDaniel P. Berrange errp) < 0) { 5473e308f20SDaniel P. Berrange goto cleanup; 5483e308f20SDaniel P. Berrange } 5493e308f20SDaniel P. Berrange 5503e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 5513e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 5523e308f20SDaniel P. Berrange /* Success, we got the right master key */ 5533e308f20SDaniel P. Berrange ret = 1; 5543e308f20SDaniel P. Berrange goto cleanup; 5553e308f20SDaniel P. Berrange } 5563e308f20SDaniel P. Berrange 5573e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 5583e308f20SDaniel P. Berrange * tell caller to try another slot */ 5593e308f20SDaniel P. Berrange ret = 0; 5603e308f20SDaniel P. Berrange 5613e308f20SDaniel P. Berrange cleanup: 5623e308f20SDaniel P. Berrange qcrypto_ivgen_free(ivgen); 5633e308f20SDaniel P. Berrange qcrypto_cipher_free(cipher); 5643e308f20SDaniel P. Berrange g_free(splitkey); 5653e308f20SDaniel P. Berrange g_free(possiblekey); 5663e308f20SDaniel P. Berrange return ret; 5673e308f20SDaniel P. Berrange } 5683e308f20SDaniel P. Berrange 5693e308f20SDaniel P. Berrange 5703e308f20SDaniel P. Berrange /* 5713e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 5723e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 5733e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 5743e308f20SDaniel P. Berrange * 5753e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 5763e308f20SDaniel P. Berrange */ 5773e308f20SDaniel P. Berrange static int 5783e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 5793e308f20SDaniel P. Berrange const char *password, 5803e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg, 5813e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode, 5823e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 5833e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg, 5843e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg, 5853e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash, 5863e308f20SDaniel P. Berrange uint8_t **masterkey, 5873e308f20SDaniel P. Berrange size_t *masterkeylen, 5883e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 5893e308f20SDaniel P. Berrange void *opaque, 5903e308f20SDaniel P. Berrange Error **errp) 5913e308f20SDaniel P. Berrange { 5923e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 5933e308f20SDaniel P. Berrange size_t i; 5943e308f20SDaniel P. Berrange int rv; 5953e308f20SDaniel P. Berrange 5963e308f20SDaniel P. Berrange *masterkey = g_new0(uint8_t, luks->header.key_bytes); 5973e308f20SDaniel P. Berrange *masterkeylen = luks->header.key_bytes; 5983e308f20SDaniel P. Berrange 5993e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 6003e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 6013e308f20SDaniel P. Berrange &luks->header.key_slots[i], 6023e308f20SDaniel P. Berrange password, 6033e308f20SDaniel P. Berrange cipheralg, 6043e308f20SDaniel P. Berrange ciphermode, 6053e308f20SDaniel P. Berrange hash, 6063e308f20SDaniel P. Berrange ivalg, 6073e308f20SDaniel P. Berrange ivcipheralg, 6083e308f20SDaniel P. Berrange ivhash, 6093e308f20SDaniel P. Berrange *masterkey, 6103e308f20SDaniel P. Berrange *masterkeylen, 6113e308f20SDaniel P. Berrange readfunc, 6123e308f20SDaniel P. Berrange opaque, 6133e308f20SDaniel P. Berrange errp); 6143e308f20SDaniel P. Berrange if (rv < 0) { 6153e308f20SDaniel P. Berrange goto error; 6163e308f20SDaniel P. Berrange } 6173e308f20SDaniel P. Berrange if (rv == 1) { 6183e308f20SDaniel P. Berrange return 0; 6193e308f20SDaniel P. Berrange } 6203e308f20SDaniel P. Berrange } 6213e308f20SDaniel P. Berrange 6223e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 6233e308f20SDaniel P. Berrange 6243e308f20SDaniel P. Berrange error: 6253e308f20SDaniel P. Berrange g_free(*masterkey); 6263e308f20SDaniel P. Berrange *masterkey = NULL; 6273e308f20SDaniel P. Berrange *masterkeylen = 0; 6283e308f20SDaniel P. Berrange return -1; 6293e308f20SDaniel P. Berrange } 6303e308f20SDaniel P. Berrange 6313e308f20SDaniel P. Berrange 6323e308f20SDaniel P. Berrange static int 6333e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 6343e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 6351cd9a787SDaniel P. Berrange const char *optprefix, 6363e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 6373e308f20SDaniel P. Berrange void *opaque, 6383e308f20SDaniel P. Berrange unsigned int flags, 639*c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 6403e308f20SDaniel P. Berrange Error **errp) 6413e308f20SDaniel P. Berrange { 6423e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 6433e308f20SDaniel P. Berrange Error *local_err = NULL; 6443e308f20SDaniel P. Berrange int ret = 0; 6453e308f20SDaniel P. Berrange size_t i; 6463e308f20SDaniel P. Berrange ssize_t rv; 6473e308f20SDaniel P. Berrange uint8_t *masterkey = NULL; 6483e308f20SDaniel P. Berrange size_t masterkeylen; 6493e308f20SDaniel P. Berrange char *ivgen_name, *ivhash_name; 6503e308f20SDaniel P. Berrange QCryptoCipherMode ciphermode; 6513e308f20SDaniel P. Berrange QCryptoCipherAlgorithm cipheralg; 6523e308f20SDaniel P. Berrange QCryptoIVGenAlgorithm ivalg; 6533e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg; 6543e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash; 6553e308f20SDaniel P. Berrange QCryptoHashAlgorithm ivhash; 6563e308f20SDaniel P. Berrange char *password = NULL; 6573e308f20SDaniel P. Berrange 6583e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 6593e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 6601cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 6611cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 6623e308f20SDaniel P. Berrange return -1; 6633e308f20SDaniel P. Berrange } 6643e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 6653e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 6663e308f20SDaniel P. Berrange if (!password) { 6673e308f20SDaniel P. Berrange return -1; 6683e308f20SDaniel P. Berrange } 6693e308f20SDaniel P. Berrange } 6703e308f20SDaniel P. Berrange 6713e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 6723e308f20SDaniel P. Berrange block->opaque = luks; 6733e308f20SDaniel P. Berrange 6743e308f20SDaniel P. Berrange /* Read the entire LUKS header, minus the key material from 6753e308f20SDaniel P. Berrange * the underlying device */ 676e4a3507eSDaniel P. Berrange rv = readfunc(block, 0, 6773e308f20SDaniel P. Berrange (uint8_t *)&luks->header, 6783e308f20SDaniel P. Berrange sizeof(luks->header), 679e4a3507eSDaniel P. Berrange opaque, 68037509233SFam Zheng errp); 6813e308f20SDaniel P. Berrange if (rv < 0) { 6823e308f20SDaniel P. Berrange ret = rv; 6833e308f20SDaniel P. Berrange goto fail; 6843e308f20SDaniel P. Berrange } 6853e308f20SDaniel P. Berrange 6863e308f20SDaniel P. Berrange /* The header is always stored in big-endian format, so 6873e308f20SDaniel P. Berrange * convert everything to native */ 6883e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 6893e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.payload_offset); 6903e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_bytes); 6913e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 6923e308f20SDaniel P. Berrange 6933e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 6943e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 6953e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 6963e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].key_offset); 6973e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 6983e308f20SDaniel P. Berrange } 6993e308f20SDaniel P. Berrange 7003e308f20SDaniel P. Berrange if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 7013e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 7023e308f20SDaniel P. Berrange error_setg(errp, "Volume is not in LUKS format"); 7033e308f20SDaniel P. Berrange ret = -EINVAL; 7043e308f20SDaniel P. Berrange goto fail; 7053e308f20SDaniel P. Berrange } 7063e308f20SDaniel P. Berrange if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 7073e308f20SDaniel P. Berrange error_setg(errp, "LUKS version %" PRIu32 " is not supported", 7083e308f20SDaniel P. Berrange luks->header.version); 7093e308f20SDaniel P. Berrange ret = -ENOTSUP; 7103e308f20SDaniel P. Berrange goto fail; 7113e308f20SDaniel P. Berrange } 7123e308f20SDaniel P. Berrange 7133e308f20SDaniel P. Berrange /* 7143e308f20SDaniel P. Berrange * The cipher_mode header contains a string that we have 7153e308f20SDaniel P. Berrange * to further parse, of the format 7163e308f20SDaniel P. Berrange * 7173e308f20SDaniel P. Berrange * <cipher-mode>-<iv-generator>[:<iv-hash>] 7183e308f20SDaniel P. Berrange * 7193e308f20SDaniel P. Berrange * eg cbc-essiv:sha256, cbc-plain64 7203e308f20SDaniel P. Berrange */ 7213e308f20SDaniel P. Berrange ivgen_name = strchr(luks->header.cipher_mode, '-'); 7223e308f20SDaniel P. Berrange if (!ivgen_name) { 7233e308f20SDaniel P. Berrange ret = -EINVAL; 7243e308f20SDaniel P. Berrange error_setg(errp, "Unexpected cipher mode string format %s", 7253e308f20SDaniel P. Berrange luks->header.cipher_mode); 7263e308f20SDaniel P. Berrange goto fail; 7273e308f20SDaniel P. Berrange } 7283e308f20SDaniel P. Berrange *ivgen_name = '\0'; 7293e308f20SDaniel P. Berrange ivgen_name++; 7303e308f20SDaniel P. Berrange 7313e308f20SDaniel P. Berrange ivhash_name = strchr(ivgen_name, ':'); 7323e308f20SDaniel P. Berrange if (!ivhash_name) { 7333e308f20SDaniel P. Berrange ivhash = 0; 7343e308f20SDaniel P. Berrange } else { 7353e308f20SDaniel P. Berrange *ivhash_name = '\0'; 7363e308f20SDaniel P. Berrange ivhash_name++; 7373e308f20SDaniel P. Berrange 7383e308f20SDaniel P. Berrange ivhash = qcrypto_block_luks_hash_name_lookup(ivhash_name, 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 7473e308f20SDaniel P. Berrange ciphermode = qcrypto_block_luks_cipher_mode_lookup(luks->header.cipher_mode, 7483e308f20SDaniel P. Berrange &local_err); 7493e308f20SDaniel P. Berrange if (local_err) { 7503e308f20SDaniel P. Berrange ret = -ENOTSUP; 7513e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7523e308f20SDaniel P. Berrange goto fail; 7533e308f20SDaniel P. Berrange } 7543e308f20SDaniel P. Berrange 7553e308f20SDaniel P. Berrange cipheralg = qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 7563e308f20SDaniel P. Berrange ciphermode, 7573e308f20SDaniel P. Berrange luks->header.key_bytes, 7583e308f20SDaniel P. Berrange &local_err); 7593e308f20SDaniel P. Berrange if (local_err) { 7603e308f20SDaniel P. Berrange ret = -ENOTSUP; 7613e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7623e308f20SDaniel P. Berrange goto fail; 7633e308f20SDaniel P. Berrange } 7643e308f20SDaniel P. Berrange 7653e308f20SDaniel P. Berrange hash = qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 7663e308f20SDaniel P. Berrange &local_err); 7673e308f20SDaniel P. Berrange if (local_err) { 7683e308f20SDaniel P. Berrange ret = -ENOTSUP; 7693e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7703e308f20SDaniel P. Berrange goto fail; 7713e308f20SDaniel P. Berrange } 7723e308f20SDaniel P. Berrange 7733e308f20SDaniel P. Berrange ivalg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 7743e308f20SDaniel P. Berrange &local_err); 7753e308f20SDaniel P. Berrange if (local_err) { 7763e308f20SDaniel P. Berrange ret = -ENOTSUP; 7773e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7783e308f20SDaniel P. Berrange goto fail; 7793e308f20SDaniel P. Berrange } 7803e308f20SDaniel P. Berrange 7813e308f20SDaniel P. Berrange if (ivalg == QCRYPTO_IVGEN_ALG_ESSIV) { 7828b7cdba3SDaniel P. Berrange if (!ivhash_name) { 7838b7cdba3SDaniel P. Berrange ret = -EINVAL; 7848b7cdba3SDaniel P. Berrange error_setg(errp, "Missing IV generator hash specification"); 7858b7cdba3SDaniel P. Berrange goto fail; 7868b7cdba3SDaniel P. Berrange } 7873e308f20SDaniel P. Berrange ivcipheralg = qcrypto_block_luks_essiv_cipher(cipheralg, 7883e308f20SDaniel P. Berrange ivhash, 7893e308f20SDaniel P. Berrange &local_err); 7903e308f20SDaniel P. Berrange if (local_err) { 7913e308f20SDaniel P. Berrange ret = -ENOTSUP; 7923e308f20SDaniel P. Berrange error_propagate(errp, local_err); 7933e308f20SDaniel P. Berrange goto fail; 7943e308f20SDaniel P. Berrange } 7953e308f20SDaniel P. Berrange } else { 7968b7cdba3SDaniel P. Berrange /* Note we parsed the ivhash_name earlier in the cipher_mode 7978b7cdba3SDaniel P. Berrange * spec string even with plain/plain64 ivgens, but we 7988b7cdba3SDaniel P. Berrange * will ignore it, since it is irrelevant for these ivgens. 7998b7cdba3SDaniel P. Berrange * This is for compat with dm-crypt which will silently 8008b7cdba3SDaniel P. Berrange * ignore hash names with these ivgens rather than report 8018b7cdba3SDaniel P. Berrange * an error about the invalid usage 8028b7cdba3SDaniel P. Berrange */ 8033e308f20SDaniel P. Berrange ivcipheralg = cipheralg; 8043e308f20SDaniel P. Berrange } 8053e308f20SDaniel P. Berrange 8063e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 8073e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 8083e308f20SDaniel P. Berrange * and unlock the master key from that slot. 8093e308f20SDaniel P. Berrange */ 8103e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 8113e308f20SDaniel P. Berrange password, 8123e308f20SDaniel P. Berrange cipheralg, ciphermode, 8133e308f20SDaniel P. Berrange hash, 8143e308f20SDaniel P. Berrange ivalg, 8153e308f20SDaniel P. Berrange ivcipheralg, 8163e308f20SDaniel P. Berrange ivhash, 8173e308f20SDaniel P. Berrange &masterkey, &masterkeylen, 8183e308f20SDaniel P. Berrange readfunc, opaque, 8193e308f20SDaniel P. Berrange errp) < 0) { 8203e308f20SDaniel P. Berrange ret = -EACCES; 8213e308f20SDaniel P. Berrange goto fail; 8223e308f20SDaniel P. Berrange } 8233e308f20SDaniel P. Berrange 8243e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 8253e308f20SDaniel P. Berrange * block device payload decryption objects 8263e308f20SDaniel P. Berrange */ 8273e308f20SDaniel P. Berrange block->kdfhash = hash; 8283e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(cipheralg, 8293e308f20SDaniel P. Berrange ciphermode); 8303e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(ivalg, 8313e308f20SDaniel P. Berrange ivcipheralg, 8323e308f20SDaniel P. Berrange ivhash, 8333e308f20SDaniel P. Berrange masterkey, masterkeylen, 8343e308f20SDaniel P. Berrange errp); 8353e308f20SDaniel P. Berrange if (!block->ivgen) { 8363e308f20SDaniel P. Berrange ret = -ENOTSUP; 8373e308f20SDaniel P. Berrange goto fail; 8383e308f20SDaniel P. Berrange } 8393e308f20SDaniel P. Berrange 840*c972fa12SVladimir Sementsov-Ogievskiy ret = qcrypto_block_init_cipher(block, cipheralg, ciphermode, 841*c972fa12SVladimir Sementsov-Ogievskiy masterkey, masterkeylen, n_threads, 8423e308f20SDaniel P. Berrange errp); 843*c972fa12SVladimir Sementsov-Ogievskiy if (ret < 0) { 8443e308f20SDaniel P. Berrange ret = -ENOTSUP; 8453e308f20SDaniel P. Berrange goto fail; 8463e308f20SDaniel P. Berrange } 8473e308f20SDaniel P. Berrange } 8483e308f20SDaniel P. Berrange 849850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 8503e308f20SDaniel P. Berrange block->payload_offset = luks->header.payload_offset * 851850f49deSDaniel P. Berrange block->sector_size; 8523e308f20SDaniel P. Berrange 85340c85028SDaniel P. Berrange luks->cipher_alg = cipheralg; 85440c85028SDaniel P. Berrange luks->cipher_mode = ciphermode; 85540c85028SDaniel P. Berrange luks->ivgen_alg = ivalg; 85640c85028SDaniel P. Berrange luks->ivgen_hash_alg = ivhash; 85740c85028SDaniel P. Berrange luks->hash_alg = hash; 85840c85028SDaniel P. Berrange 8593e308f20SDaniel P. Berrange g_free(masterkey); 8603e308f20SDaniel P. Berrange g_free(password); 8613e308f20SDaniel P. Berrange 8623e308f20SDaniel P. Berrange return 0; 8633e308f20SDaniel P. Berrange 8643e308f20SDaniel P. Berrange fail: 8653e308f20SDaniel P. Berrange g_free(masterkey); 866*c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 8673e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 8683e308f20SDaniel P. Berrange g_free(luks); 8693e308f20SDaniel P. Berrange g_free(password); 8703e308f20SDaniel P. Berrange return ret; 8713e308f20SDaniel P. Berrange } 8723e308f20SDaniel P. Berrange 8733e308f20SDaniel P. Berrange 8742ef950f9SFam Zheng static void 8752ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 8763e308f20SDaniel P. Berrange { 8772ef950f9SFam Zheng QemuUUID uuid; 8782ef950f9SFam Zheng qemu_uuid_generate(&uuid); 8792ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 8803e308f20SDaniel P. Berrange } 8813e308f20SDaniel P. Berrange 8823e308f20SDaniel P. Berrange static int 8833e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 8843e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 8851cd9a787SDaniel P. Berrange const char *optprefix, 8863e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 8873e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 8883e308f20SDaniel P. Berrange void *opaque, 8893e308f20SDaniel P. Berrange Error **errp) 8903e308f20SDaniel P. Berrange { 8913e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 8923e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 8933e308f20SDaniel P. Berrange Error *local_err = NULL; 8943e308f20SDaniel P. Berrange uint8_t *masterkey = NULL; 8953e308f20SDaniel P. Berrange uint8_t *slotkey = NULL; 8963e308f20SDaniel P. Berrange uint8_t *splitkey = NULL; 8973e308f20SDaniel P. Berrange size_t splitkeylen = 0; 8983e308f20SDaniel P. Berrange size_t i; 8993e308f20SDaniel P. Berrange QCryptoCipher *cipher = NULL; 9003e308f20SDaniel P. Berrange QCryptoIVGen *ivgen = NULL; 9013e308f20SDaniel P. Berrange char *password; 9023e308f20SDaniel P. Berrange const char *cipher_alg; 9033e308f20SDaniel P. Berrange const char *cipher_mode; 9043e308f20SDaniel P. Berrange const char *ivgen_alg; 9053e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 9063e308f20SDaniel P. Berrange const char *hash_alg; 9073e308f20SDaniel P. Berrange char *cipher_mode_spec = NULL; 9083e308f20SDaniel P. Berrange QCryptoCipherAlgorithm ivcipheralg = 0; 90959b060beSDaniel P. Berrange uint64_t iters; 9103e308f20SDaniel P. Berrange 9113e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 9123bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 9132ab66cd5SDaniel P. Berrange luks_opts.iter_time = 2000; 9143bd18890SDaniel P. Berrange } 9153e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 9163e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 9173e308f20SDaniel P. Berrange } 9183e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 9193e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 9203e308f20SDaniel P. Berrange } 9213e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 9223e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 9233e308f20SDaniel P. Berrange } 9243e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 9253e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 9263e308f20SDaniel P. Berrange } 9278b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9288b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 9298b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 9308b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 9318b7cdba3SDaniel P. Berrange } 9328b7cdba3SDaniel P. Berrange } 9338b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 9348b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 9358b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 9363e308f20SDaniel P. Berrange 9373e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 9381cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 9391cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 9403e308f20SDaniel P. Berrange return -1; 9413e308f20SDaniel P. Berrange } 9423e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 9433e308f20SDaniel P. Berrange if (!password) { 9443e308f20SDaniel P. Berrange return -1; 9453e308f20SDaniel P. Berrange } 9463e308f20SDaniel P. Berrange 9473e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 9483e308f20SDaniel P. Berrange block->opaque = luks; 9493e308f20SDaniel P. Berrange 9503e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 9513e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 9523e308f20SDaniel P. Berrange 9533e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 9543e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 9553e308f20SDaniel P. Berrange * it out to disk 9563e308f20SDaniel P. Berrange */ 9573e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 9582ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 9593e308f20SDaniel P. Berrange 9603e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 9613e308f20SDaniel P. Berrange errp); 9623e308f20SDaniel P. Berrange if (!cipher_alg) { 9633e308f20SDaniel P. Berrange goto error; 9643e308f20SDaniel P. Berrange } 9653e308f20SDaniel P. Berrange 966977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 967977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 9683e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 969977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 9703e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 9713e308f20SDaniel P. Berrange ivgen_hash_alg); 9723e308f20SDaniel P. Berrange } else { 9733e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 9743e308f20SDaniel P. Berrange } 975977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 9763e308f20SDaniel P. Berrange 9773e308f20SDaniel P. Berrange 9783e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 9793e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 9803e308f20SDaniel P. Berrange cipher_alg); 9813e308f20SDaniel P. Berrange goto error; 9823e308f20SDaniel P. Berrange } 9833e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 9843e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 9853e308f20SDaniel P. Berrange cipher_mode_spec); 9863e308f20SDaniel P. Berrange goto error; 9873e308f20SDaniel P. Berrange } 9883e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 9893e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 9903e308f20SDaniel P. Berrange hash_alg); 9913e308f20SDaniel P. Berrange goto error; 9923e308f20SDaniel P. Berrange } 9933e308f20SDaniel P. Berrange 9943e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 9953e308f20SDaniel P. Berrange ivcipheralg = qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 9963e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 9973e308f20SDaniel P. Berrange &local_err); 9983e308f20SDaniel P. Berrange if (local_err) { 9993e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10003e308f20SDaniel P. Berrange goto error; 10013e308f20SDaniel P. Berrange } 10023e308f20SDaniel P. Berrange } else { 10033e308f20SDaniel P. Berrange ivcipheralg = luks_opts.cipher_alg; 10043e308f20SDaniel P. Berrange } 10053e308f20SDaniel P. Berrange 10063e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 10073e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 10083e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 10093e308f20SDaniel P. Berrange 10103e308f20SDaniel P. Berrange luks->header.key_bytes = qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 10113e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 10123e308f20SDaniel P. Berrange luks->header.key_bytes *= 2; 10133e308f20SDaniel P. Berrange } 10143e308f20SDaniel P. Berrange 10153e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 10163e308f20SDaniel P. Berrange * with PBKDF later 10173e308f20SDaniel P. Berrange */ 10183e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 10193e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10203e308f20SDaniel P. Berrange errp) < 0) { 10213e308f20SDaniel P. Berrange goto error; 10223e308f20SDaniel P. Berrange } 10233e308f20SDaniel P. Berrange 10243e308f20SDaniel P. Berrange /* Generate random master key */ 10253e308f20SDaniel P. Berrange masterkey = g_new0(uint8_t, luks->header.key_bytes); 10263e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 10273e308f20SDaniel P. Berrange luks->header.key_bytes, errp) < 0) { 10283e308f20SDaniel P. Berrange goto error; 10293e308f20SDaniel P. Berrange } 10303e308f20SDaniel P. Berrange 10313e308f20SDaniel P. Berrange 10323e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1033*c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1034*c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1035*c972fa12SVladimir Sementsov-Ogievskiy luks->header.key_bytes, 1, errp) < 0) { 10363e308f20SDaniel P. Berrange goto error; 10373e308f20SDaniel P. Berrange } 10383e308f20SDaniel P. Berrange 10393e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 10403e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 10413e308f20SDaniel P. Berrange luks_opts.cipher_mode); 10423e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 10433e308f20SDaniel P. Berrange ivcipheralg, 10443e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 10453e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10463e308f20SDaniel P. Berrange errp); 10473e308f20SDaniel P. Berrange 10483e308f20SDaniel P. Berrange if (!block->ivgen) { 10493e308f20SDaniel P. Berrange goto error; 10503e308f20SDaniel P. Berrange } 10513e308f20SDaniel P. Berrange 10523e308f20SDaniel P. Berrange 10533e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 10543e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 10553e308f20SDaniel P. Berrange */ 105659b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 10573e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10583e308f20SDaniel P. Berrange luks->header.master_key_salt, 10593e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1060e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 10613e308f20SDaniel P. Berrange &local_err); 10623e308f20SDaniel P. Berrange if (local_err) { 10633e308f20SDaniel P. Berrange error_propagate(errp, local_err); 10643e308f20SDaniel P. Berrange goto error; 10653e308f20SDaniel P. Berrange } 10663e308f20SDaniel P. Berrange 10673bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 10683bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 10693bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 10703bd18890SDaniel P. Berrange (unsigned long long)iters); 10713bd18890SDaniel P. Berrange goto error; 10723bd18890SDaniel P. Berrange } 10733bd18890SDaniel P. Berrange 10743bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 10753bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 10763bd18890SDaniel P. Berrange 10773e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 10783e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 10793e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 10803e308f20SDaniel P. Berrange * in total time to check all keys */ 108159b060beSDaniel P. Berrange iters /= 8; 108259b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 108359b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 108459b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 108559b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 108659b060beSDaniel P. Berrange goto error; 108759b060beSDaniel P. Berrange } 108859b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 108959b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 10903e308f20SDaniel P. Berrange 10913e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 10923e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 10933e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 10943e308f20SDaniel P. Berrange * valid master key 10953e308f20SDaniel P. Berrange */ 10963e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 10973e308f20SDaniel P. Berrange masterkey, luks->header.key_bytes, 10983e308f20SDaniel P. Berrange luks->header.master_key_salt, 10993e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11003e308f20SDaniel P. Berrange luks->header.master_key_iterations, 11013e308f20SDaniel P. Berrange luks->header.master_key_digest, 11023e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 11033e308f20SDaniel P. Berrange errp) < 0) { 11043e308f20SDaniel P. Berrange goto error; 11053e308f20SDaniel P. Berrange } 11063e308f20SDaniel P. Berrange 11073e308f20SDaniel P. Berrange 11083e308f20SDaniel P. Berrange /* Although LUKS has multiple key slots, we're just going 11093e308f20SDaniel P. Berrange * to use the first key slot */ 11103e308f20SDaniel P. Berrange splitkeylen = luks->header.key_bytes * QCRYPTO_BLOCK_LUKS_STRIPES; 11113e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 11123e308f20SDaniel P. Berrange luks->header.key_slots[i].active = i == 0 ? 11133e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED : 11143e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 11153e308f20SDaniel P. Berrange luks->header.key_slots[i].stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 11163e308f20SDaniel P. Berrange 11173e308f20SDaniel P. Berrange /* This calculation doesn't match that shown in the spec, 11183e308f20SDaniel P. Berrange * but instead follows the cryptsetup implementation. 11193e308f20SDaniel P. Berrange */ 11203e308f20SDaniel P. Berrange luks->header.key_slots[i].key_offset = 11213e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11223e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1123207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 11243e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 11253e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i); 11263e308f20SDaniel P. Berrange } 11273e308f20SDaniel P. Berrange 11283e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.key_slots[0].salt, 11293e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11303e308f20SDaniel P. Berrange errp) < 0) { 11313e308f20SDaniel P. Berrange goto error; 11323e308f20SDaniel P. Berrange } 11333e308f20SDaniel P. Berrange 11343e308f20SDaniel P. Berrange /* Again we determine how many iterations are required to 11353e308f20SDaniel P. Berrange * hash the user password while consuming 1 second of compute 11363e308f20SDaniel P. Berrange * time */ 113759b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 11383e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11393e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11403e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1141e74aabcfSDaniel P. Berrange luks->header.key_bytes, 11423e308f20SDaniel P. Berrange &local_err); 11433e308f20SDaniel P. Berrange if (local_err) { 11443e308f20SDaniel P. Berrange error_propagate(errp, local_err); 11453e308f20SDaniel P. Berrange goto error; 11463e308f20SDaniel P. Berrange } 11473bd18890SDaniel P. Berrange 11483bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 11493bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 11503bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 11513bd18890SDaniel P. Berrange (unsigned long long)iters); 11523bd18890SDaniel P. Berrange goto error; 11533bd18890SDaniel P. Berrange } 11543bd18890SDaniel P. Berrange 11553bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 11563bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 11573bd18890SDaniel P. Berrange 115859b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 115959b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 116059b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 116159b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 116259b060beSDaniel P. Berrange goto error; 116359b060beSDaniel P. Berrange } 116459b060beSDaniel P. Berrange 116559b060beSDaniel P. Berrange luks->header.key_slots[0].iterations = 116659b060beSDaniel P. Berrange MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 11673e308f20SDaniel P. Berrange 11683e308f20SDaniel P. Berrange 11693e308f20SDaniel P. Berrange /* Generate a key that we'll use to encrypt the master 11703e308f20SDaniel P. Berrange * key, from the user's password 11713e308f20SDaniel P. Berrange */ 11723e308f20SDaniel P. Berrange slotkey = g_new0(uint8_t, luks->header.key_bytes); 11733e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 11743e308f20SDaniel P. Berrange (uint8_t *)password, strlen(password), 11753e308f20SDaniel P. Berrange luks->header.key_slots[0].salt, 11763e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 11773e308f20SDaniel P. Berrange luks->header.key_slots[0].iterations, 11783e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11793e308f20SDaniel P. Berrange errp) < 0) { 11803e308f20SDaniel P. Berrange goto error; 11813e308f20SDaniel P. Berrange } 11823e308f20SDaniel P. Berrange 11833e308f20SDaniel P. Berrange 11843e308f20SDaniel P. Berrange /* Setup the encryption objects needed to encrypt the 11853e308f20SDaniel P. Berrange * master key material 11863e308f20SDaniel P. Berrange */ 11873e308f20SDaniel P. Berrange cipher = qcrypto_cipher_new(luks_opts.cipher_alg, 11883e308f20SDaniel P. Berrange luks_opts.cipher_mode, 11893e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11903e308f20SDaniel P. Berrange errp); 11913e308f20SDaniel P. Berrange if (!cipher) { 11923e308f20SDaniel P. Berrange goto error; 11933e308f20SDaniel P. Berrange } 11943e308f20SDaniel P. Berrange 11953e308f20SDaniel P. Berrange ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 11963e308f20SDaniel P. Berrange ivcipheralg, 11973e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 11983e308f20SDaniel P. Berrange slotkey, luks->header.key_bytes, 11993e308f20SDaniel P. Berrange errp); 12003e308f20SDaniel P. Berrange if (!ivgen) { 12013e308f20SDaniel P. Berrange goto error; 12023e308f20SDaniel P. Berrange } 12033e308f20SDaniel P. Berrange 12043e308f20SDaniel P. Berrange /* Before storing the master key, we need to vastly 12053e308f20SDaniel P. Berrange * increase its size, as protection against forensic 12063e308f20SDaniel P. Berrange * disk data recovery */ 12073e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 12083e308f20SDaniel P. Berrange 12093e308f20SDaniel P. Berrange if (qcrypto_afsplit_encode(luks_opts.hash_alg, 12103e308f20SDaniel P. Berrange luks->header.key_bytes, 12113e308f20SDaniel P. Berrange luks->header.key_slots[0].stripes, 12123e308f20SDaniel P. Berrange masterkey, 12133e308f20SDaniel P. Berrange splitkey, 12143e308f20SDaniel P. Berrange errp) < 0) { 12153e308f20SDaniel P. Berrange goto error; 12163e308f20SDaniel P. Berrange } 12173e308f20SDaniel P. Berrange 12183e308f20SDaniel P. Berrange /* Now we encrypt the split master key with the key generated 12193e308f20SDaniel P. Berrange * from the user's password, before storing it */ 12200270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 12213e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 12223e308f20SDaniel P. Berrange 0, 12233e308f20SDaniel P. Berrange splitkey, 12243e308f20SDaniel P. Berrange splitkeylen, 12253e308f20SDaniel P. Berrange errp) < 0) { 12263e308f20SDaniel P. Berrange goto error; 12273e308f20SDaniel P. Berrange } 12283e308f20SDaniel P. Berrange 12293e308f20SDaniel P. Berrange 12303e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 12313e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 12323e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 12333e308f20SDaniel P. Berrange * to the nearest sector */ 12343e308f20SDaniel P. Berrange luks->header.payload_offset = 12353e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12363e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) + 1237207ba7c8SLaurent Vivier (ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE), 12383e308f20SDaniel P. Berrange (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 12393e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * 12403e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 12413e308f20SDaniel P. Berrange 1242850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 12433e308f20SDaniel P. Berrange block->payload_offset = luks->header.payload_offset * 1244850f49deSDaniel P. Berrange block->sector_size; 12453e308f20SDaniel P. Berrange 12463e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1247e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 12483e308f20SDaniel P. Berrange if (local_err) { 12493e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12503e308f20SDaniel P. Berrange goto error; 12513e308f20SDaniel P. Berrange } 12523e308f20SDaniel P. Berrange 12533e308f20SDaniel P. Berrange /* Everything on disk uses Big Endian, so flip header fields 12543e308f20SDaniel P. Berrange * before writing them */ 12553e308f20SDaniel P. Berrange cpu_to_be16s(&luks->header.version); 12563e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.payload_offset); 12573e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_bytes); 12583e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.master_key_iterations); 12593e308f20SDaniel P. Berrange 12603e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12613e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].active); 12623e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].iterations); 12633e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].key_offset); 12643e308f20SDaniel P. Berrange cpu_to_be32s(&luks->header.key_slots[i].stripes); 12653e308f20SDaniel P. Berrange } 12663e308f20SDaniel P. Berrange 12673e308f20SDaniel P. Berrange 12683e308f20SDaniel P. Berrange /* Write out the partition header and key slot headers */ 1269e4a3507eSDaniel P. Berrange writefunc(block, 0, 12703e308f20SDaniel P. Berrange (const uint8_t *)&luks->header, 12713e308f20SDaniel P. Berrange sizeof(luks->header), 1272e4a3507eSDaniel P. Berrange opaque, 127337509233SFam Zheng &local_err); 12743e308f20SDaniel P. Berrange 12753e308f20SDaniel P. Berrange /* Delay checking local_err until we've byte-swapped */ 12763e308f20SDaniel P. Berrange 12773e308f20SDaniel P. Berrange /* Byte swap the header back to native, in case we need 12783e308f20SDaniel P. Berrange * to read it again later */ 12793e308f20SDaniel P. Berrange be16_to_cpus(&luks->header.version); 12803e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.payload_offset); 12813e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_bytes); 12823e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.master_key_iterations); 12833e308f20SDaniel P. Berrange 12843e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 12853e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].active); 12863e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].iterations); 12873e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].key_offset); 12883e308f20SDaniel P. Berrange be32_to_cpus(&luks->header.key_slots[i].stripes); 12893e308f20SDaniel P. Berrange } 12903e308f20SDaniel P. Berrange 12913e308f20SDaniel P. Berrange if (local_err) { 12923e308f20SDaniel P. Berrange error_propagate(errp, local_err); 12933e308f20SDaniel P. Berrange goto error; 12943e308f20SDaniel P. Berrange } 12953e308f20SDaniel P. Berrange 12963e308f20SDaniel P. Berrange /* Write out the master key material, starting at the 12973e308f20SDaniel P. Berrange * sector immediately following the partition header. */ 1298e4a3507eSDaniel P. Berrange if (writefunc(block, 12993e308f20SDaniel P. Berrange luks->header.key_slots[0].key_offset * 13003e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 13013e308f20SDaniel P. Berrange splitkey, splitkeylen, 1302e4a3507eSDaniel P. Berrange opaque, 130337509233SFam Zheng errp) != splitkeylen) { 13043e308f20SDaniel P. Berrange goto error; 13053e308f20SDaniel P. Berrange } 13063e308f20SDaniel P. Berrange 130740c85028SDaniel P. Berrange luks->cipher_alg = luks_opts.cipher_alg; 130840c85028SDaniel P. Berrange luks->cipher_mode = luks_opts.cipher_mode; 130940c85028SDaniel P. Berrange luks->ivgen_alg = luks_opts.ivgen_alg; 131040c85028SDaniel P. Berrange luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 131140c85028SDaniel P. Berrange luks->hash_alg = luks_opts.hash_alg; 131240c85028SDaniel P. Berrange 13133e308f20SDaniel P. Berrange memset(masterkey, 0, luks->header.key_bytes); 13143e308f20SDaniel P. Berrange g_free(masterkey); 13153e308f20SDaniel P. Berrange memset(slotkey, 0, luks->header.key_bytes); 13163e308f20SDaniel P. Berrange g_free(slotkey); 13173e308f20SDaniel P. Berrange g_free(splitkey); 13183e308f20SDaniel P. Berrange g_free(password); 13193e308f20SDaniel P. Berrange g_free(cipher_mode_spec); 13203e308f20SDaniel P. Berrange 13213e308f20SDaniel P. Berrange qcrypto_ivgen_free(ivgen); 13223e308f20SDaniel P. Berrange qcrypto_cipher_free(cipher); 13233e308f20SDaniel P. Berrange 13243e308f20SDaniel P. Berrange return 0; 13253e308f20SDaniel P. Berrange 13263e308f20SDaniel P. Berrange error: 13273e308f20SDaniel P. Berrange if (masterkey) { 13283e308f20SDaniel P. Berrange memset(masterkey, 0, luks->header.key_bytes); 13293e308f20SDaniel P. Berrange } 13303e308f20SDaniel P. Berrange g_free(masterkey); 13313e308f20SDaniel P. Berrange if (slotkey) { 13323e308f20SDaniel P. Berrange memset(slotkey, 0, luks->header.key_bytes); 13333e308f20SDaniel P. Berrange } 13343e308f20SDaniel P. Berrange g_free(slotkey); 13353e308f20SDaniel P. Berrange g_free(splitkey); 13363e308f20SDaniel P. Berrange g_free(password); 13373e308f20SDaniel P. Berrange g_free(cipher_mode_spec); 13383e308f20SDaniel P. Berrange 13393e308f20SDaniel P. Berrange qcrypto_ivgen_free(ivgen); 13403e308f20SDaniel P. Berrange qcrypto_cipher_free(cipher); 13413e308f20SDaniel P. Berrange 1342*c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1343b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1344b640adcaSVladimir Sementsov-Ogievskiy 13453e308f20SDaniel P. Berrange g_free(luks); 13463e308f20SDaniel P. Berrange return -1; 13473e308f20SDaniel P. Berrange } 13483e308f20SDaniel P. Berrange 13493e308f20SDaniel P. Berrange 135040c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 135140c85028SDaniel P. Berrange QCryptoBlockInfo *info, 135240c85028SDaniel P. Berrange Error **errp) 135340c85028SDaniel P. Berrange { 135440c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 135540c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 135640c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlotList *slots = NULL, **prev = &info->u.luks.slots; 135740c85028SDaniel P. Berrange size_t i; 135840c85028SDaniel P. Berrange 135940c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 136040c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 136140c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 136240c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 136340c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 136440c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 136540c85028SDaniel P. Berrange } 136640c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 136740c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 136840c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 136940c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 137040c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 137140c85028SDaniel P. Berrange 137240c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 137340c85028SDaniel P. Berrange slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1); 137440c85028SDaniel P. Berrange *prev = slots; 137540c85028SDaniel P. Berrange 137640c85028SDaniel P. Berrange slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 137740c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 137840c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 137940c85028SDaniel P. Berrange slot->key_offset = luks->header.key_slots[i].key_offset 138040c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 138140c85028SDaniel P. Berrange if (slot->active) { 138240c85028SDaniel P. Berrange slot->has_iters = true; 138340c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 138440c85028SDaniel P. Berrange slot->has_stripes = true; 138540c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 138640c85028SDaniel P. Berrange } 138740c85028SDaniel P. Berrange 138840c85028SDaniel P. Berrange prev = &slots->next; 138940c85028SDaniel P. Berrange } 139040c85028SDaniel P. Berrange 139140c85028SDaniel P. Berrange return 0; 139240c85028SDaniel P. Berrange } 139340c85028SDaniel P. Berrange 139440c85028SDaniel P. Berrange 13953e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 13963e308f20SDaniel P. Berrange { 13973e308f20SDaniel P. Berrange g_free(block->opaque); 13983e308f20SDaniel P. Berrange } 13993e308f20SDaniel P. Berrange 14003e308f20SDaniel P. Berrange 14013e308f20SDaniel P. Berrange static int 14023e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 14034609742aSDaniel P. Berrange uint64_t offset, 14043e308f20SDaniel P. Berrange uint8_t *buf, 14053e308f20SDaniel P. Berrange size_t len, 14063e308f20SDaniel P. Berrange Error **errp) 14073e308f20SDaniel P. Berrange { 14084609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 14094609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 14100f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 14113e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 14124609742aSDaniel P. Berrange offset, buf, len, errp); 14133e308f20SDaniel P. Berrange } 14143e308f20SDaniel P. Berrange 14153e308f20SDaniel P. Berrange 14163e308f20SDaniel P. Berrange static int 14173e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 14184609742aSDaniel P. Berrange uint64_t offset, 14193e308f20SDaniel P. Berrange uint8_t *buf, 14203e308f20SDaniel P. Berrange size_t len, 14213e308f20SDaniel P. Berrange Error **errp) 14223e308f20SDaniel P. Berrange { 14234609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 14244609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 14250f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 14263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 14274609742aSDaniel P. Berrange offset, buf, len, errp); 14283e308f20SDaniel P. Berrange } 14293e308f20SDaniel P. Berrange 14303e308f20SDaniel P. Berrange 14313e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 14323e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 14333e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 143440c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 14353e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 14363e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 14373e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 14383e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 14393e308f20SDaniel P. Berrange }; 1440