xref: /qemu/crypto/block-luks.c (revision c5f69628)
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"
35557d2bdcSMaxim Levitsky #include "qemu/bitmap.h"
363e308f20SDaniel P. Berrange 
373e308f20SDaniel P. Berrange /*
383e308f20SDaniel P. Berrange  * Reference for the LUKS format implemented here is
393e308f20SDaniel P. Berrange  *
403e308f20SDaniel P. Berrange  *   docs/on-disk-format.pdf
413e308f20SDaniel P. Berrange  *
423e308f20SDaniel P. Berrange  * in 'cryptsetup' package source code
433e308f20SDaniel P. Berrange  *
443e308f20SDaniel P. Berrange  * This file implements the 1.2.1 specification, dated
453e308f20SDaniel P. Berrange  * Oct 16, 2011.
463e308f20SDaniel P. Berrange  */
473e308f20SDaniel P. Berrange 
483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS;
493e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSHeader QCryptoBlockLUKSHeader;
503e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot;
513e308f20SDaniel P. Berrange 
523e308f20SDaniel P. Berrange 
533e308f20SDaniel P. Berrange /* The following constants are all defined by the LUKS spec */
543e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_VERSION 1
553e308f20SDaniel P. Berrange 
563e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MAGIC_LEN 6
573e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN 32
583e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN 32
593e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN 32
603e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_DIGEST_LEN 20
613e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SALT_LEN 32
623e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_UUID_LEN 40
633e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS 8
643e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_STRIPES 4000
653e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS 1000
663e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS 1000
673e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET 4096
683e308f20SDaniel P. Berrange 
693e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED 0x0000DEAD
703e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3
713e308f20SDaniel P. Berrange 
723e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL
733e308f20SDaniel P. Berrange 
74557d2bdcSMaxim Levitsky #define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS 2000
75557d2bdcSMaxim Levitsky #define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40
76557d2bdcSMaxim Levitsky 
773e308f20SDaniel P. Berrange static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
783e308f20SDaniel P. Berrange     'L', 'U', 'K', 'S', 0xBA, 0xBE
793e308f20SDaniel P. Berrange };
803e308f20SDaniel P. Berrange 
813e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap;
823e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap {
833e308f20SDaniel P. Berrange     const char *name;
843e308f20SDaniel P. Berrange     int id;
853e308f20SDaniel P. Berrange };
863e308f20SDaniel P. Berrange 
873e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap;
883e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap {
893e308f20SDaniel P. Berrange     uint32_t key_bytes;
903e308f20SDaniel P. Berrange     int id;
913e308f20SDaniel P. Berrange };
923e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap;
933e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap {
943e308f20SDaniel P. Berrange     const char *name;
953e308f20SDaniel P. Berrange     const QCryptoBlockLUKSCipherSizeMap *sizes;
963e308f20SDaniel P. Berrange };
973e308f20SDaniel P. Berrange 
983e308f20SDaniel P. Berrange 
993e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1003e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = {
1013e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_AES_128 },
1023e308f20SDaniel P. Berrange     { 24, QCRYPTO_CIPHER_ALG_AES_192 },
1033e308f20SDaniel P. Berrange     { 32, QCRYPTO_CIPHER_ALG_AES_256 },
1043e308f20SDaniel P. Berrange     { 0, 0 },
1053e308f20SDaniel P. Berrange };
1063e308f20SDaniel P. Berrange 
1073e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1083e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = {
1093e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_CAST5_128 },
1103e308f20SDaniel P. Berrange     { 0, 0 },
1113e308f20SDaniel P. Berrange };
1123e308f20SDaniel P. Berrange 
1133e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1143e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = {
1153e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 },
1163e308f20SDaniel P. Berrange     { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 },
1173e308f20SDaniel P. Berrange     { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 },
1183e308f20SDaniel P. Berrange     { 0, 0 },
1193e308f20SDaniel P. Berrange };
1203e308f20SDaniel P. Berrange 
1213e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1223e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = {
1233e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 },
1243e308f20SDaniel P. Berrange     { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 },
1253e308f20SDaniel P. Berrange     { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 },
1263e308f20SDaniel P. Berrange     { 0, 0 },
1273e308f20SDaniel P. Berrange };
1283e308f20SDaniel P. Berrange 
1293e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap
1303e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = {
1313e308f20SDaniel P. Berrange     { "aes", qcrypto_block_luks_cipher_size_map_aes },
1323e308f20SDaniel P. Berrange     { "cast5", qcrypto_block_luks_cipher_size_map_cast5 },
1333e308f20SDaniel P. Berrange     { "serpent", qcrypto_block_luks_cipher_size_map_serpent },
1343e308f20SDaniel P. Berrange     { "twofish", qcrypto_block_luks_cipher_size_map_twofish },
1353e308f20SDaniel P. Berrange };
1363e308f20SDaniel P. Berrange 
1373e308f20SDaniel P. Berrange 
1383e308f20SDaniel P. Berrange /*
1393e308f20SDaniel P. Berrange  * This struct is written to disk in big-endian format,
1403e308f20SDaniel P. Berrange  * but operated upon in native-endian format.
1413e308f20SDaniel P. Berrange  */
1423e308f20SDaniel P. Berrange struct QCryptoBlockLUKSKeySlot {
1433e308f20SDaniel P. Berrange     /* state of keyslot, enabled/disable */
1443e308f20SDaniel P. Berrange     uint32_t active;
1453e308f20SDaniel P. Berrange     /* iterations for PBKDF2 */
1463e308f20SDaniel P. Berrange     uint32_t iterations;
1473e308f20SDaniel P. Berrange     /* salt for PBKDF2 */
1483e308f20SDaniel P. Berrange     uint8_t salt[QCRYPTO_BLOCK_LUKS_SALT_LEN];
1493e308f20SDaniel P. Berrange     /* start sector of key material */
150f0d3c362SMaxim Levitsky     uint32_t key_offset_sector;
1513e308f20SDaniel P. Berrange     /* number of anti-forensic stripes */
1523e308f20SDaniel P. Berrange     uint32_t stripes;
1535993e3beSGreg Kurz };
1543e308f20SDaniel P. Berrange 
1553e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
1563e308f20SDaniel P. Berrange 
1573e308f20SDaniel P. Berrange 
1583e308f20SDaniel P. Berrange /*
1593e308f20SDaniel P. Berrange  * This struct is written to disk in big-endian format,
1603e308f20SDaniel P. Berrange  * but operated upon in native-endian format.
1613e308f20SDaniel P. Berrange  */
1623e308f20SDaniel P. Berrange struct QCryptoBlockLUKSHeader {
1633e308f20SDaniel P. Berrange     /* 'L', 'U', 'K', 'S', '0xBA', '0xBE' */
1643e308f20SDaniel P. Berrange     char magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN];
1653e308f20SDaniel P. Berrange 
1663e308f20SDaniel P. Berrange     /* LUKS version, currently 1 */
1673e308f20SDaniel P. Berrange     uint16_t version;
1683e308f20SDaniel P. Berrange 
1693e308f20SDaniel P. Berrange     /* cipher name specification (aes, etc) */
1703e308f20SDaniel P. Berrange     char cipher_name[QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN];
1713e308f20SDaniel P. Berrange 
1723e308f20SDaniel P. Berrange     /* cipher mode specification (cbc-plain, xts-essiv:sha256, etc) */
1733e308f20SDaniel P. Berrange     char cipher_mode[QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN];
1743e308f20SDaniel P. Berrange 
1753e308f20SDaniel P. Berrange     /* hash specification (sha256, etc) */
1763e308f20SDaniel P. Berrange     char hash_spec[QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN];
1773e308f20SDaniel P. Berrange 
1783e308f20SDaniel P. Berrange     /* start offset of the volume data (in 512 byte sectors) */
179f0d3c362SMaxim Levitsky     uint32_t payload_offset_sector;
1803e308f20SDaniel P. Berrange 
1813e308f20SDaniel P. Berrange     /* Number of key bytes */
182f0d3c362SMaxim Levitsky     uint32_t master_key_len;
1833e308f20SDaniel P. Berrange 
1843e308f20SDaniel P. Berrange     /* master key checksum after PBKDF2 */
1853e308f20SDaniel P. Berrange     uint8_t master_key_digest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
1863e308f20SDaniel P. Berrange 
1873e308f20SDaniel P. Berrange     /* salt for master key PBKDF2 */
1883e308f20SDaniel P. Berrange     uint8_t master_key_salt[QCRYPTO_BLOCK_LUKS_SALT_LEN];
1893e308f20SDaniel P. Berrange 
1903e308f20SDaniel P. Berrange     /* iterations for master key PBKDF2 */
1913e308f20SDaniel P. Berrange     uint32_t master_key_iterations;
1923e308f20SDaniel P. Berrange 
1933e308f20SDaniel P. Berrange     /* UUID of the partition in standard ASCII representation */
1943e308f20SDaniel P. Berrange     uint8_t uuid[QCRYPTO_BLOCK_LUKS_UUID_LEN];
1953e308f20SDaniel P. Berrange 
1963e308f20SDaniel P. Berrange     /* key slots */
1973e308f20SDaniel P. Berrange     QCryptoBlockLUKSKeySlot key_slots[QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS];
1985993e3beSGreg Kurz };
1993e308f20SDaniel P. Berrange 
2003e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592);
2013e308f20SDaniel P. Berrange 
2023e308f20SDaniel P. Berrange 
2033e308f20SDaniel P. Berrange struct QCryptoBlockLUKS {
2043e308f20SDaniel P. Berrange     QCryptoBlockLUKSHeader header;
20540c85028SDaniel P. Berrange 
2069d80e59dSMaxim Levitsky     /* Main encryption algorithm used for encryption*/
20740c85028SDaniel P. Berrange     QCryptoCipherAlgorithm cipher_alg;
2089d80e59dSMaxim Levitsky 
2099d80e59dSMaxim Levitsky     /* Mode of encryption for the selected encryption algorithm */
21040c85028SDaniel P. Berrange     QCryptoCipherMode cipher_mode;
2119d80e59dSMaxim Levitsky 
2129d80e59dSMaxim Levitsky     /* Initialization vector generation algorithm */
21340c85028SDaniel P. Berrange     QCryptoIVGenAlgorithm ivgen_alg;
2149d80e59dSMaxim Levitsky 
2159d80e59dSMaxim Levitsky     /* Hash algorithm used for IV generation*/
21640c85028SDaniel P. Berrange     QCryptoHashAlgorithm ivgen_hash_alg;
2179d80e59dSMaxim Levitsky 
2189d80e59dSMaxim Levitsky     /*
2199d80e59dSMaxim Levitsky      * Encryption algorithm used for IV generation.
2209d80e59dSMaxim Levitsky      * Usually the same as main encryption algorithm
2219d80e59dSMaxim Levitsky      */
2229d80e59dSMaxim Levitsky     QCryptoCipherAlgorithm ivgen_cipher_alg;
2239d80e59dSMaxim Levitsky 
2249d80e59dSMaxim Levitsky     /* Hash algorithm used in pbkdf2 function */
22540c85028SDaniel P. Berrange     QCryptoHashAlgorithm hash_alg;
226557d2bdcSMaxim Levitsky 
227557d2bdcSMaxim Levitsky     /* Name of the secret that was used to open the image */
228557d2bdcSMaxim Levitsky     char *secret;
2293e308f20SDaniel P. Berrange };
2303e308f20SDaniel P. Berrange 
2313e308f20SDaniel P. Berrange 
2323e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name,
2333e308f20SDaniel P. Berrange                                                  QCryptoCipherMode mode,
2343e308f20SDaniel P. Berrange                                                  uint32_t key_bytes,
2353e308f20SDaniel P. Berrange                                                  Error **errp)
2363e308f20SDaniel P. Berrange {
2373e308f20SDaniel P. Berrange     const QCryptoBlockLUKSCipherNameMap *map =
2383e308f20SDaniel P. Berrange         qcrypto_block_luks_cipher_name_map;
2393e308f20SDaniel P. Berrange     size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map);
2403e308f20SDaniel P. Berrange     size_t i, j;
2413e308f20SDaniel P. Berrange 
2423e308f20SDaniel P. Berrange     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
2433e308f20SDaniel P. Berrange         key_bytes /= 2;
2443e308f20SDaniel P. Berrange     }
2453e308f20SDaniel P. Berrange 
2463e308f20SDaniel P. Berrange     for (i = 0; i < maplen; i++) {
2473e308f20SDaniel P. Berrange         if (!g_str_equal(map[i].name, name)) {
2483e308f20SDaniel P. Berrange             continue;
2493e308f20SDaniel P. Berrange         }
2503e308f20SDaniel P. Berrange         for (j = 0; j < map[i].sizes[j].key_bytes; j++) {
2513e308f20SDaniel P. Berrange             if (map[i].sizes[j].key_bytes == key_bytes) {
2523e308f20SDaniel P. Berrange                 return map[i].sizes[j].id;
2533e308f20SDaniel P. Berrange             }
2543e308f20SDaniel P. Berrange         }
2553e308f20SDaniel P. Berrange     }
2563e308f20SDaniel P. Berrange 
2573e308f20SDaniel P. Berrange     error_setg(errp, "Algorithm %s with key size %d bytes not supported",
2583e308f20SDaniel P. Berrange                name, key_bytes);
2593e308f20SDaniel P. Berrange     return 0;
2603e308f20SDaniel P. Berrange }
2613e308f20SDaniel P. Berrange 
2623e308f20SDaniel P. Berrange static const char *
2633e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
2643e308f20SDaniel P. Berrange                                      Error **errp)
2653e308f20SDaniel P. Berrange {
2663e308f20SDaniel P. Berrange     const QCryptoBlockLUKSCipherNameMap *map =
2673e308f20SDaniel P. Berrange         qcrypto_block_luks_cipher_name_map;
2683e308f20SDaniel P. Berrange     size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map);
2693e308f20SDaniel P. Berrange     size_t i, j;
2703e308f20SDaniel P. Berrange     for (i = 0; i < maplen; i++) {
2713e308f20SDaniel P. Berrange         for (j = 0; j < map[i].sizes[j].key_bytes; j++) {
2723e308f20SDaniel P. Berrange             if (map[i].sizes[j].id == alg) {
2733e308f20SDaniel P. Berrange                 return map[i].name;
2743e308f20SDaniel P. Berrange             }
2753e308f20SDaniel P. Berrange         }
2763e308f20SDaniel P. Berrange     }
2773e308f20SDaniel P. Berrange 
2783e308f20SDaniel P. Berrange     error_setg(errp, "Algorithm '%s' not supported",
279977c736fSMarkus Armbruster                QCryptoCipherAlgorithm_str(alg));
2803e308f20SDaniel P. Berrange     return NULL;
2813e308f20SDaniel P. Berrange }
2823e308f20SDaniel P. Berrange 
2833e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can
2843e308f20SDaniel P. Berrange  * make that function emit a more friendly error message */
2853e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name,
286f7abe0ecSMarc-André Lureau                                           const QEnumLookup *map,
2873e308f20SDaniel P. Berrange                                           const char *type,
2883e308f20SDaniel P. Berrange                                           Error **errp)
2893e308f20SDaniel P. Berrange {
2909ae33079SMarkus Armbruster     int ret = qapi_enum_parse(map, name, -1, NULL);
2913e308f20SDaniel P. Berrange 
2929ae33079SMarkus Armbruster     if (ret < 0) {
2933e308f20SDaniel P. Berrange         error_setg(errp, "%s %s not supported", type, name);
2943e308f20SDaniel P. Berrange         return 0;
2953e308f20SDaniel P. Berrange     }
2969ae33079SMarkus Armbruster     return ret;
2979ae33079SMarkus Armbruster }
2983e308f20SDaniel P. Berrange 
2993e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp)               \
3003e308f20SDaniel P. Berrange     qcrypto_block_luks_name_lookup(name,                                \
301f7abe0ecSMarc-André Lureau                                    &QCryptoCipherMode_lookup,           \
3023e308f20SDaniel P. Berrange                                    "Cipher mode",                       \
3033e308f20SDaniel P. Berrange                                    errp)
3043e308f20SDaniel P. Berrange 
3053e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp)                 \
3063e308f20SDaniel P. Berrange     qcrypto_block_luks_name_lookup(name,                                \
307f7abe0ecSMarc-André Lureau                                    &QCryptoHashAlgorithm_lookup,        \
3083e308f20SDaniel P. Berrange                                    "Hash algorithm",                    \
3093e308f20SDaniel P. Berrange                                    errp)
3103e308f20SDaniel P. Berrange 
3113e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp)                \
3123e308f20SDaniel P. Berrange     qcrypto_block_luks_name_lookup(name,                                \
313f7abe0ecSMarc-André Lureau                                    &QCryptoIVGenAlgorithm_lookup,       \
3143e308f20SDaniel P. Berrange                                    "IV generator",                      \
3153e308f20SDaniel P. Berrange                                    errp)
3163e308f20SDaniel P. Berrange 
3173e308f20SDaniel P. Berrange 
3183e308f20SDaniel P. Berrange static bool
3193e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf,
3203e308f20SDaniel P. Berrange                               size_t buf_size)
3213e308f20SDaniel P. Berrange {
3223e308f20SDaniel P. Berrange     const QCryptoBlockLUKSHeader *luks_header = (const void *)buf;
3233e308f20SDaniel P. Berrange 
3243e308f20SDaniel P. Berrange     if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) &&
3253e308f20SDaniel P. Berrange         memcmp(luks_header->magic, qcrypto_block_luks_magic,
3263e308f20SDaniel P. Berrange                QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 &&
3273e308f20SDaniel P. Berrange         be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) {
3283e308f20SDaniel P. Berrange         return true;
3293e308f20SDaniel P. Berrange     } else {
3303e308f20SDaniel P. Berrange         return false;
3313e308f20SDaniel P. Berrange     }
3323e308f20SDaniel P. Berrange }
3333e308f20SDaniel P. Berrange 
3343e308f20SDaniel P. Berrange 
3353e308f20SDaniel P. Berrange /**
3363e308f20SDaniel P. Berrange  * Deal with a quirk of dm-crypt usage of ESSIV.
3373e308f20SDaniel P. Berrange  *
3383e308f20SDaniel P. Berrange  * When calculating ESSIV IVs, the cipher length used by ESSIV
3393e308f20SDaniel P. Berrange  * may be different from the cipher length used for the block
3403e308f20SDaniel P. Berrange  * encryption, becauses dm-crypt uses the hash digest length
3413e308f20SDaniel P. Berrange  * as the key size. ie, if you have AES 128 as the block cipher
3423e308f20SDaniel P. Berrange  * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as
3433e308f20SDaniel P. Berrange  * the cipher since that gets a key length matching the digest
3443e308f20SDaniel P. Berrange  * size, not AES 128 with truncated digest as might be imagined
3453e308f20SDaniel P. Berrange  */
3463e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm
3473e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,
3483e308f20SDaniel P. Berrange                                 QCryptoHashAlgorithm hash,
3493e308f20SDaniel P. Berrange                                 Error **errp)
3503e308f20SDaniel P. Berrange {
3513e308f20SDaniel P. Berrange     size_t digestlen = qcrypto_hash_digest_len(hash);
3523e308f20SDaniel P. Berrange     size_t keylen = qcrypto_cipher_get_key_len(cipher);
3533e308f20SDaniel P. Berrange     if (digestlen == keylen) {
3543e308f20SDaniel P. Berrange         return cipher;
3553e308f20SDaniel P. Berrange     }
3563e308f20SDaniel P. Berrange 
3573e308f20SDaniel P. Berrange     switch (cipher) {
3583e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_AES_128:
3593e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_AES_192:
3603e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_AES_256:
3613e308f20SDaniel P. Berrange         if (digestlen == qcrypto_cipher_get_key_len(
3623e308f20SDaniel P. Berrange                 QCRYPTO_CIPHER_ALG_AES_128)) {
3633e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_AES_128;
3643e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3653e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_AES_192)) {
3663e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_AES_192;
3673e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3683e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_AES_256)) {
3693e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_AES_256;
3703e308f20SDaniel P. Berrange         } else {
3713e308f20SDaniel P. Berrange             error_setg(errp, "No AES cipher with key size %zu available",
3723e308f20SDaniel P. Berrange                        digestlen);
3733e308f20SDaniel P. Berrange             return 0;
3743e308f20SDaniel P. Berrange         }
3753e308f20SDaniel P. Berrange         break;
3763e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_SERPENT_128:
3773e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_SERPENT_192:
3783e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_SERPENT_256:
3793e308f20SDaniel P. Berrange         if (digestlen == qcrypto_cipher_get_key_len(
3803e308f20SDaniel P. Berrange                 QCRYPTO_CIPHER_ALG_SERPENT_128)) {
3813e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_SERPENT_128;
3823e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3833e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_SERPENT_192)) {
3843e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_SERPENT_192;
3853e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3863e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_SERPENT_256)) {
3873e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_SERPENT_256;
3883e308f20SDaniel P. Berrange         } else {
3893e308f20SDaniel P. Berrange             error_setg(errp, "No Serpent cipher with key size %zu available",
3903e308f20SDaniel P. Berrange                        digestlen);
3913e308f20SDaniel P. Berrange             return 0;
3923e308f20SDaniel P. Berrange         }
3933e308f20SDaniel P. Berrange         break;
3943e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
3953e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_TWOFISH_192:
3963e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
3973e308f20SDaniel P. Berrange         if (digestlen == qcrypto_cipher_get_key_len(
3983e308f20SDaniel P. Berrange                 QCRYPTO_CIPHER_ALG_TWOFISH_128)) {
3993e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_TWOFISH_128;
4003e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
4013e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_TWOFISH_192)) {
4023e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_TWOFISH_192;
4033e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
4043e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_TWOFISH_256)) {
4053e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_TWOFISH_256;
4063e308f20SDaniel P. Berrange         } else {
4073e308f20SDaniel P. Berrange             error_setg(errp, "No Twofish cipher with key size %zu available",
4083e308f20SDaniel P. Berrange                        digestlen);
4093e308f20SDaniel P. Berrange             return 0;
4103e308f20SDaniel P. Berrange         }
4113e308f20SDaniel P. Berrange         break;
4123e308f20SDaniel P. Berrange     default:
4133e308f20SDaniel P. Berrange         error_setg(errp, "Cipher %s not supported with essiv",
414977c736fSMarkus Armbruster                    QCryptoCipherAlgorithm_str(cipher));
4153e308f20SDaniel P. Berrange         return 0;
4163e308f20SDaniel P. Berrange     }
4173e308f20SDaniel P. Berrange }
4183e308f20SDaniel P. Berrange 
4193e308f20SDaniel P. Berrange /*
420bd56a55aSMaxim Levitsky  * Returns number of sectors needed to store the key material
421bd56a55aSMaxim Levitsky  * given number of anti forensic stripes
422bd56a55aSMaxim Levitsky  */
423bd56a55aSMaxim Levitsky static int
424bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks,
425bd56a55aSMaxim Levitsky                                        unsigned int header_sectors,
426bd56a55aSMaxim Levitsky                                        unsigned int stripes)
427bd56a55aSMaxim Levitsky {
428bd56a55aSMaxim Levitsky     /*
429bd56a55aSMaxim Levitsky      * This calculation doesn't match that shown in the spec,
430bd56a55aSMaxim Levitsky      * but instead follows the cryptsetup implementation.
431bd56a55aSMaxim Levitsky      */
432bd56a55aSMaxim Levitsky 
433bd56a55aSMaxim Levitsky     size_t splitkeylen = luks->header.master_key_len * stripes;
434bd56a55aSMaxim Levitsky 
435bd56a55aSMaxim Levitsky     /* First align the key material size to block size*/
436bd56a55aSMaxim Levitsky     size_t splitkeylen_sectors =
437bd56a55aSMaxim Levitsky         DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE);
438bd56a55aSMaxim Levitsky 
439bd56a55aSMaxim Levitsky     /* Then also align the key material size to the size of the header */
440bd56a55aSMaxim Levitsky     return ROUND_UP(splitkeylen_sectors, header_sectors);
441bd56a55aSMaxim Levitsky }
442bd56a55aSMaxim Levitsky 
443bd56a55aSMaxim Levitsky /*
444dde2c5afSMaxim Levitsky  * Stores the main LUKS header, taking care of endianess
445dde2c5afSMaxim Levitsky  */
446dde2c5afSMaxim Levitsky static int
447dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block,
448dde2c5afSMaxim Levitsky                                 QCryptoBlockWriteFunc writefunc,
449dde2c5afSMaxim Levitsky                                 void *opaque,
450dde2c5afSMaxim Levitsky                                 Error **errp)
451dde2c5afSMaxim Levitsky {
452dde2c5afSMaxim Levitsky     const QCryptoBlockLUKS *luks = block->opaque;
453dde2c5afSMaxim Levitsky     Error *local_err = NULL;
454dde2c5afSMaxim Levitsky     size_t i;
455dde2c5afSMaxim Levitsky     g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL;
456dde2c5afSMaxim Levitsky 
457dde2c5afSMaxim Levitsky     /* Create a copy of the header */
458dde2c5afSMaxim Levitsky     hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1);
459dde2c5afSMaxim Levitsky     memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader));
460dde2c5afSMaxim Levitsky 
461dde2c5afSMaxim Levitsky     /*
462dde2c5afSMaxim Levitsky      * Everything on disk uses Big Endian (tm), so flip header fields
463dde2c5afSMaxim Levitsky      * before writing them
464dde2c5afSMaxim Levitsky      */
465dde2c5afSMaxim Levitsky     cpu_to_be16s(&hdr_copy->version);
466dde2c5afSMaxim Levitsky     cpu_to_be32s(&hdr_copy->payload_offset_sector);
467dde2c5afSMaxim Levitsky     cpu_to_be32s(&hdr_copy->master_key_len);
468dde2c5afSMaxim Levitsky     cpu_to_be32s(&hdr_copy->master_key_iterations);
469dde2c5afSMaxim Levitsky 
470dde2c5afSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
471dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].active);
472dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].iterations);
473dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].key_offset_sector);
474dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].stripes);
475dde2c5afSMaxim Levitsky     }
476dde2c5afSMaxim Levitsky 
477dde2c5afSMaxim Levitsky     /* Write out the partition header and key slot headers */
478dde2c5afSMaxim Levitsky     writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy),
479dde2c5afSMaxim Levitsky               opaque, &local_err);
480dde2c5afSMaxim Levitsky 
481dde2c5afSMaxim Levitsky     if (local_err) {
482dde2c5afSMaxim Levitsky         error_propagate(errp, local_err);
483dde2c5afSMaxim Levitsky         return -1;
484dde2c5afSMaxim Levitsky     }
485dde2c5afSMaxim Levitsky     return 0;
486dde2c5afSMaxim Levitsky }
487dde2c5afSMaxim Levitsky 
488dde2c5afSMaxim Levitsky /*
489dde2c5afSMaxim Levitsky  * Loads the main LUKS header,and byteswaps it to native endianess
490dde2c5afSMaxim Levitsky  * And run basic sanity checks on it
491dde2c5afSMaxim Levitsky  */
492dde2c5afSMaxim Levitsky static int
493dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block,
494dde2c5afSMaxim Levitsky                                 QCryptoBlockReadFunc readfunc,
495dde2c5afSMaxim Levitsky                                 void *opaque,
496dde2c5afSMaxim Levitsky                                 Error **errp)
497dde2c5afSMaxim Levitsky {
498757dda54SAlberto Faria     int rv;
499dde2c5afSMaxim Levitsky     size_t i;
500dde2c5afSMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
501dde2c5afSMaxim Levitsky 
502dde2c5afSMaxim Levitsky     /*
503dde2c5afSMaxim Levitsky      * Read the entire LUKS header, minus the key material from
504dde2c5afSMaxim Levitsky      * the underlying device
505dde2c5afSMaxim Levitsky      */
506dde2c5afSMaxim Levitsky     rv = readfunc(block, 0,
507dde2c5afSMaxim Levitsky                   (uint8_t *)&luks->header,
508dde2c5afSMaxim Levitsky                   sizeof(luks->header),
509dde2c5afSMaxim Levitsky                   opaque,
510dde2c5afSMaxim Levitsky                   errp);
511dde2c5afSMaxim Levitsky     if (rv < 0) {
512dde2c5afSMaxim Levitsky         return rv;
513dde2c5afSMaxim Levitsky     }
514dde2c5afSMaxim Levitsky 
515dde2c5afSMaxim Levitsky     /*
516dde2c5afSMaxim Levitsky      * The header is always stored in big-endian format, so
517dde2c5afSMaxim Levitsky      * convert everything to native
518dde2c5afSMaxim Levitsky      */
519dde2c5afSMaxim Levitsky     be16_to_cpus(&luks->header.version);
520dde2c5afSMaxim Levitsky     be32_to_cpus(&luks->header.payload_offset_sector);
521dde2c5afSMaxim Levitsky     be32_to_cpus(&luks->header.master_key_len);
522dde2c5afSMaxim Levitsky     be32_to_cpus(&luks->header.master_key_iterations);
523dde2c5afSMaxim Levitsky 
524dde2c5afSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
525dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].active);
526dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].iterations);
527dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].key_offset_sector);
528dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].stripes);
529dde2c5afSMaxim Levitsky     }
530dde2c5afSMaxim Levitsky 
531dde2c5afSMaxim Levitsky     return 0;
532dde2c5afSMaxim Levitsky }
533dde2c5afSMaxim Levitsky 
534dde2c5afSMaxim Levitsky /*
5359fa9c1c2SMaxim Levitsky  * Does basic sanity checks on the LUKS header
5369fa9c1c2SMaxim Levitsky  */
5379fa9c1c2SMaxim Levitsky static int
5389fa9c1c2SMaxim Levitsky qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
5399fa9c1c2SMaxim Levitsky {
540befdba9eSMaxim Levitsky     size_t i, j;
541befdba9eSMaxim Levitsky 
542befdba9eSMaxim Levitsky     unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
543befdba9eSMaxim Levitsky         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
544befdba9eSMaxim Levitsky 
5459fa9c1c2SMaxim Levitsky     if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
5469fa9c1c2SMaxim Levitsky                QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
5479fa9c1c2SMaxim Levitsky         error_setg(errp, "Volume is not in LUKS format");
5489fa9c1c2SMaxim Levitsky         return -1;
5499fa9c1c2SMaxim Levitsky     }
5509fa9c1c2SMaxim Levitsky 
5519fa9c1c2SMaxim Levitsky     if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) {
5529fa9c1c2SMaxim Levitsky         error_setg(errp, "LUKS version %" PRIu32 " is not supported",
5539fa9c1c2SMaxim Levitsky                    luks->header.version);
5549fa9c1c2SMaxim Levitsky         return -1;
5559fa9c1c2SMaxim Levitsky     }
556befdba9eSMaxim Levitsky 
557c1d8634cSDaniel P. Berrangé     if (!memchr(luks->header.cipher_name, '\0',
558c1d8634cSDaniel P. Berrangé                 sizeof(luks->header.cipher_name))) {
559c1d8634cSDaniel P. Berrangé         error_setg(errp, "LUKS header cipher name is not NUL terminated");
560c1d8634cSDaniel P. Berrangé         return -1;
561c1d8634cSDaniel P. Berrangé     }
562c1d8634cSDaniel P. Berrangé 
563c1d8634cSDaniel P. Berrangé     if (!memchr(luks->header.cipher_mode, '\0',
564c1d8634cSDaniel P. Berrangé                 sizeof(luks->header.cipher_mode))) {
565c1d8634cSDaniel P. Berrangé         error_setg(errp, "LUKS header cipher mode is not NUL terminated");
566c1d8634cSDaniel P. Berrangé         return -1;
567c1d8634cSDaniel P. Berrangé     }
568c1d8634cSDaniel P. Berrangé 
569c1d8634cSDaniel P. Berrangé     if (!memchr(luks->header.hash_spec, '\0',
570c1d8634cSDaniel P. Berrangé                 sizeof(luks->header.hash_spec))) {
571c1d8634cSDaniel P. Berrangé         error_setg(errp, "LUKS header hash spec is not NUL terminated");
572c1d8634cSDaniel P. Berrangé         return -1;
573c1d8634cSDaniel P. Berrangé     }
574c1d8634cSDaniel P. Berrangé 
575d233fbc3SDaniel P. Berrangé     if (luks->header.payload_offset_sector <
576d233fbc3SDaniel P. Berrangé         DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET,
577d233fbc3SDaniel P. Berrangé                      QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) {
578d233fbc3SDaniel P. Berrangé         error_setg(errp, "LUKS payload is overlapping with the header");
579d233fbc3SDaniel P. Berrangé         return -1;
580d233fbc3SDaniel P. Berrangé     }
581d233fbc3SDaniel P. Berrangé 
582befdba9eSMaxim Levitsky     /* Check all keyslots for corruption  */
583befdba9eSMaxim Levitsky     for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) {
584befdba9eSMaxim Levitsky 
585befdba9eSMaxim Levitsky         const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i];
586befdba9eSMaxim Levitsky         unsigned int start1 = slot1->key_offset_sector;
587befdba9eSMaxim Levitsky         unsigned int len1 =
588befdba9eSMaxim Levitsky             qcrypto_block_luks_splitkeylen_sectors(luks,
589befdba9eSMaxim Levitsky                                                    header_sectors,
590befdba9eSMaxim Levitsky                                                    slot1->stripes);
591befdba9eSMaxim Levitsky 
592f1195961SDaniel P. Berrangé         if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) {
593f1195961SDaniel P. Berrangé             error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)",
594f1195961SDaniel P. Berrangé                        i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES);
595befdba9eSMaxim Levitsky             return -1;
596befdba9eSMaxim Levitsky         }
597befdba9eSMaxim Levitsky 
598befdba9eSMaxim Levitsky         if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED &&
599befdba9eSMaxim Levitsky             slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
600befdba9eSMaxim Levitsky             error_setg(errp,
601befdba9eSMaxim Levitsky                        "Keyslot %zu state (active/disable) is corrupted", i);
602befdba9eSMaxim Levitsky             return -1;
603befdba9eSMaxim Levitsky         }
604befdba9eSMaxim Levitsky 
605c5f69628SDaniel P. Berrangé         if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET,
60693569c37SDaniel P. Berrangé                                   QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) {
60793569c37SDaniel P. Berrangé             error_setg(errp,
60893569c37SDaniel P. Berrangé                        "Keyslot %zu is overlapping with the LUKS header",
60993569c37SDaniel P. Berrangé                        i);
61093569c37SDaniel P. Berrangé             return -1;
61193569c37SDaniel P. Berrangé         }
61293569c37SDaniel P. Berrangé 
613befdba9eSMaxim Levitsky         if (start1 + len1 > luks->header.payload_offset_sector) {
614befdba9eSMaxim Levitsky             error_setg(errp,
615befdba9eSMaxim Levitsky                        "Keyslot %zu is overlapping with the encrypted payload",
616befdba9eSMaxim Levitsky                        i);
617befdba9eSMaxim Levitsky             return -1;
618befdba9eSMaxim Levitsky         }
619befdba9eSMaxim Levitsky 
620befdba9eSMaxim Levitsky         for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) {
621befdba9eSMaxim Levitsky             const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j];
622befdba9eSMaxim Levitsky             unsigned int start2 = slot2->key_offset_sector;
623befdba9eSMaxim Levitsky             unsigned int len2 =
624befdba9eSMaxim Levitsky                 qcrypto_block_luks_splitkeylen_sectors(luks,
625befdba9eSMaxim Levitsky                                                        header_sectors,
626befdba9eSMaxim Levitsky                                                        slot2->stripes);
627befdba9eSMaxim Levitsky 
628befdba9eSMaxim Levitsky             if (start1 + len1 > start2 && start2 + len2 > start1) {
629befdba9eSMaxim Levitsky                 error_setg(errp,
630befdba9eSMaxim Levitsky                            "Keyslots %zu and %zu are overlapping in the header",
631befdba9eSMaxim Levitsky                            i, j);
632befdba9eSMaxim Levitsky                 return -1;
633befdba9eSMaxim Levitsky             }
634befdba9eSMaxim Levitsky         }
635befdba9eSMaxim Levitsky 
636befdba9eSMaxim Levitsky     }
6379fa9c1c2SMaxim Levitsky     return 0;
6389fa9c1c2SMaxim Levitsky }
6399fa9c1c2SMaxim Levitsky 
6409fa9c1c2SMaxim Levitsky /*
6419fa9c1c2SMaxim Levitsky  * Parses the crypto parameters that are stored in the LUKS header
6429fa9c1c2SMaxim Levitsky  */
6439fa9c1c2SMaxim Levitsky 
6449fa9c1c2SMaxim Levitsky static int
6459fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp)
6469fa9c1c2SMaxim Levitsky {
6479fa9c1c2SMaxim Levitsky     g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode);
6489fa9c1c2SMaxim Levitsky     char *ivgen_name, *ivhash_name;
6499fa9c1c2SMaxim Levitsky     Error *local_err = NULL;
6509fa9c1c2SMaxim Levitsky 
6519fa9c1c2SMaxim Levitsky     /*
6529fa9c1c2SMaxim Levitsky      * The cipher_mode header contains a string that we have
6539fa9c1c2SMaxim Levitsky      * to further parse, of the format
6549fa9c1c2SMaxim Levitsky      *
6559fa9c1c2SMaxim Levitsky      *    <cipher-mode>-<iv-generator>[:<iv-hash>]
6569fa9c1c2SMaxim Levitsky      *
6579fa9c1c2SMaxim Levitsky      * eg  cbc-essiv:sha256, cbc-plain64
6589fa9c1c2SMaxim Levitsky      */
6599fa9c1c2SMaxim Levitsky     ivgen_name = strchr(cipher_mode, '-');
6609fa9c1c2SMaxim Levitsky     if (!ivgen_name) {
6619fa9c1c2SMaxim Levitsky         error_setg(errp, "Unexpected cipher mode string format %s",
6629fa9c1c2SMaxim Levitsky                    luks->header.cipher_mode);
6639fa9c1c2SMaxim Levitsky         return -1;
6649fa9c1c2SMaxim Levitsky     }
6659fa9c1c2SMaxim Levitsky     *ivgen_name = '\0';
6669fa9c1c2SMaxim Levitsky     ivgen_name++;
6679fa9c1c2SMaxim Levitsky 
6689fa9c1c2SMaxim Levitsky     ivhash_name = strchr(ivgen_name, ':');
6699fa9c1c2SMaxim Levitsky     if (!ivhash_name) {
6709fa9c1c2SMaxim Levitsky         luks->ivgen_hash_alg = 0;
6719fa9c1c2SMaxim Levitsky     } else {
6729fa9c1c2SMaxim Levitsky         *ivhash_name = '\0';
6739fa9c1c2SMaxim Levitsky         ivhash_name++;
6749fa9c1c2SMaxim Levitsky 
6759fa9c1c2SMaxim Levitsky         luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name,
6769fa9c1c2SMaxim Levitsky                                                                    &local_err);
6779fa9c1c2SMaxim Levitsky         if (local_err) {
6789fa9c1c2SMaxim Levitsky             error_propagate(errp, local_err);
6799fa9c1c2SMaxim Levitsky             return -1;
6809fa9c1c2SMaxim Levitsky         }
6819fa9c1c2SMaxim Levitsky     }
6829fa9c1c2SMaxim Levitsky 
6839fa9c1c2SMaxim Levitsky     luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode,
6849fa9c1c2SMaxim Levitsky                                                               &local_err);
6859fa9c1c2SMaxim Levitsky     if (local_err) {
6869fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
6879fa9c1c2SMaxim Levitsky         return -1;
6889fa9c1c2SMaxim Levitsky     }
6899fa9c1c2SMaxim Levitsky 
6909fa9c1c2SMaxim Levitsky     luks->cipher_alg =
6919fa9c1c2SMaxim Levitsky             qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name,
6929fa9c1c2SMaxim Levitsky                                                   luks->cipher_mode,
6939fa9c1c2SMaxim Levitsky                                                   luks->header.master_key_len,
6949fa9c1c2SMaxim Levitsky                                                   &local_err);
6959fa9c1c2SMaxim Levitsky     if (local_err) {
6969fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
6979fa9c1c2SMaxim Levitsky         return -1;
6989fa9c1c2SMaxim Levitsky     }
6999fa9c1c2SMaxim Levitsky 
7009fa9c1c2SMaxim Levitsky     luks->hash_alg =
7019fa9c1c2SMaxim Levitsky             qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec,
7029fa9c1c2SMaxim Levitsky                                                 &local_err);
7039fa9c1c2SMaxim Levitsky     if (local_err) {
7049fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
7059fa9c1c2SMaxim Levitsky         return -1;
7069fa9c1c2SMaxim Levitsky     }
7079fa9c1c2SMaxim Levitsky 
7089fa9c1c2SMaxim Levitsky     luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name,
7099fa9c1c2SMaxim Levitsky                                                            &local_err);
7109fa9c1c2SMaxim Levitsky     if (local_err) {
7119fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
7129fa9c1c2SMaxim Levitsky         return -1;
7139fa9c1c2SMaxim Levitsky     }
7149fa9c1c2SMaxim Levitsky 
7159fa9c1c2SMaxim Levitsky     if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
7169fa9c1c2SMaxim Levitsky         if (!ivhash_name) {
7179fa9c1c2SMaxim Levitsky             error_setg(errp, "Missing IV generator hash specification");
7189fa9c1c2SMaxim Levitsky             return -1;
7199fa9c1c2SMaxim Levitsky         }
7209fa9c1c2SMaxim Levitsky         luks->ivgen_cipher_alg =
7219fa9c1c2SMaxim Levitsky                 qcrypto_block_luks_essiv_cipher(luks->cipher_alg,
7229fa9c1c2SMaxim Levitsky                                                 luks->ivgen_hash_alg,
7239fa9c1c2SMaxim Levitsky                                                 &local_err);
7249fa9c1c2SMaxim Levitsky         if (local_err) {
7259fa9c1c2SMaxim Levitsky             error_propagate(errp, local_err);
7269fa9c1c2SMaxim Levitsky             return -1;
7279fa9c1c2SMaxim Levitsky         }
7289fa9c1c2SMaxim Levitsky     } else {
7299fa9c1c2SMaxim Levitsky 
7309fa9c1c2SMaxim Levitsky         /*
7319fa9c1c2SMaxim Levitsky          * Note we parsed the ivhash_name earlier in the cipher_mode
7329fa9c1c2SMaxim Levitsky          * spec string even with plain/plain64 ivgens, but we
7339fa9c1c2SMaxim Levitsky          * will ignore it, since it is irrelevant for these ivgens.
7349fa9c1c2SMaxim Levitsky          * This is for compat with dm-crypt which will silently
7359fa9c1c2SMaxim Levitsky          * ignore hash names with these ivgens rather than report
7369fa9c1c2SMaxim Levitsky          * an error about the invalid usage
7379fa9c1c2SMaxim Levitsky          */
7389fa9c1c2SMaxim Levitsky         luks->ivgen_cipher_alg = luks->cipher_alg;
7399fa9c1c2SMaxim Levitsky     }
7409fa9c1c2SMaxim Levitsky     return 0;
7419fa9c1c2SMaxim Levitsky }
7429fa9c1c2SMaxim Levitsky 
7439fa9c1c2SMaxim Levitsky /*
7443994a7c9SMaxim Levitsky  * Given a key slot,  user password, and the master key,
7453994a7c9SMaxim Levitsky  * will store the encrypted master key there, and update the
7463994a7c9SMaxim Levitsky  * in-memory header. User must then write the in-memory header
7473994a7c9SMaxim Levitsky  *
7483994a7c9SMaxim Levitsky  * Returns:
7493994a7c9SMaxim Levitsky  *    0 if the keyslot was written successfully
7503994a7c9SMaxim Levitsky  *      with the provided password
7513994a7c9SMaxim Levitsky  *   -1 if a fatal error occurred while storing the key
7523994a7c9SMaxim Levitsky  */
7533994a7c9SMaxim Levitsky static int
7543994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block,
7553994a7c9SMaxim Levitsky                              unsigned int slot_idx,
7563994a7c9SMaxim Levitsky                              const char *password,
7573994a7c9SMaxim Levitsky                              uint8_t *masterkey,
7583994a7c9SMaxim Levitsky                              uint64_t iter_time,
7593994a7c9SMaxim Levitsky                              QCryptoBlockWriteFunc writefunc,
7603994a7c9SMaxim Levitsky                              void *opaque,
7613994a7c9SMaxim Levitsky                              Error **errp)
7623994a7c9SMaxim Levitsky {
7633994a7c9SMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
764557d2bdcSMaxim Levitsky     QCryptoBlockLUKSKeySlot *slot;
7653994a7c9SMaxim Levitsky     g_autofree uint8_t *splitkey = NULL;
7663994a7c9SMaxim Levitsky     size_t splitkeylen;
7673994a7c9SMaxim Levitsky     g_autofree uint8_t *slotkey = NULL;
7683994a7c9SMaxim Levitsky     g_autoptr(QCryptoCipher) cipher = NULL;
7693994a7c9SMaxim Levitsky     g_autoptr(QCryptoIVGen) ivgen = NULL;
7703994a7c9SMaxim Levitsky     Error *local_err = NULL;
7713994a7c9SMaxim Levitsky     uint64_t iters;
7723994a7c9SMaxim Levitsky     int ret = -1;
7733994a7c9SMaxim Levitsky 
774557d2bdcSMaxim Levitsky     assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
775557d2bdcSMaxim Levitsky     slot = &luks->header.key_slots[slot_idx];
7763994a7c9SMaxim Levitsky     if (qcrypto_random_bytes(slot->salt,
7773994a7c9SMaxim Levitsky                              QCRYPTO_BLOCK_LUKS_SALT_LEN,
7783994a7c9SMaxim Levitsky                              errp) < 0) {
7793994a7c9SMaxim Levitsky         goto cleanup;
7803994a7c9SMaxim Levitsky     }
7813994a7c9SMaxim Levitsky 
7823994a7c9SMaxim Levitsky     splitkeylen = luks->header.master_key_len * slot->stripes;
7833994a7c9SMaxim Levitsky 
7843994a7c9SMaxim Levitsky     /*
7853994a7c9SMaxim Levitsky      * Determine how many iterations are required to
7863994a7c9SMaxim Levitsky      * hash the user password while consuming 1 second of compute
7873994a7c9SMaxim Levitsky      * time
7883994a7c9SMaxim Levitsky      */
7893994a7c9SMaxim Levitsky     iters = qcrypto_pbkdf2_count_iters(luks->hash_alg,
7903994a7c9SMaxim Levitsky                                        (uint8_t *)password, strlen(password),
7913994a7c9SMaxim Levitsky                                        slot->salt,
7923994a7c9SMaxim Levitsky                                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
7933994a7c9SMaxim Levitsky                                        luks->header.master_key_len,
7943994a7c9SMaxim Levitsky                                        &local_err);
7953994a7c9SMaxim Levitsky     if (local_err) {
7963994a7c9SMaxim Levitsky         error_propagate(errp, local_err);
7973994a7c9SMaxim Levitsky         goto cleanup;
7983994a7c9SMaxim Levitsky     }
7993994a7c9SMaxim Levitsky 
8003994a7c9SMaxim Levitsky     if (iters > (ULLONG_MAX / iter_time)) {
8013994a7c9SMaxim Levitsky         error_setg_errno(errp, ERANGE,
8023994a7c9SMaxim Levitsky                          "PBKDF iterations %llu too large to scale",
8033994a7c9SMaxim Levitsky                          (unsigned long long)iters);
8043994a7c9SMaxim Levitsky         goto cleanup;
8053994a7c9SMaxim Levitsky     }
8063994a7c9SMaxim Levitsky 
8073994a7c9SMaxim Levitsky     /* iter_time was in millis, but count_iters reported for secs */
8083994a7c9SMaxim Levitsky     iters = iters * iter_time / 1000;
8093994a7c9SMaxim Levitsky 
8103994a7c9SMaxim Levitsky     if (iters > UINT32_MAX) {
8113994a7c9SMaxim Levitsky         error_setg_errno(errp, ERANGE,
8123994a7c9SMaxim Levitsky                          "PBKDF iterations %llu larger than %u",
8133994a7c9SMaxim Levitsky                          (unsigned long long)iters, UINT32_MAX);
8143994a7c9SMaxim Levitsky         goto cleanup;
8153994a7c9SMaxim Levitsky     }
8163994a7c9SMaxim Levitsky 
8173994a7c9SMaxim Levitsky     slot->iterations =
8183994a7c9SMaxim Levitsky         MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS);
8193994a7c9SMaxim Levitsky 
8203994a7c9SMaxim Levitsky 
8213994a7c9SMaxim Levitsky     /*
8223994a7c9SMaxim Levitsky      * Generate a key that we'll use to encrypt the master
8233994a7c9SMaxim Levitsky      * key, from the user's password
8243994a7c9SMaxim Levitsky      */
8253994a7c9SMaxim Levitsky     slotkey = g_new0(uint8_t, luks->header.master_key_len);
8263994a7c9SMaxim Levitsky     if (qcrypto_pbkdf2(luks->hash_alg,
8273994a7c9SMaxim Levitsky                        (uint8_t *)password, strlen(password),
8283994a7c9SMaxim Levitsky                        slot->salt,
8293994a7c9SMaxim Levitsky                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
8303994a7c9SMaxim Levitsky                        slot->iterations,
8313994a7c9SMaxim Levitsky                        slotkey, luks->header.master_key_len,
8323994a7c9SMaxim Levitsky                        errp) < 0) {
8333994a7c9SMaxim Levitsky         goto cleanup;
8343994a7c9SMaxim Levitsky     }
8353994a7c9SMaxim Levitsky 
8363994a7c9SMaxim Levitsky 
8373994a7c9SMaxim Levitsky     /*
8383994a7c9SMaxim Levitsky      * Setup the encryption objects needed to encrypt the
8393994a7c9SMaxim Levitsky      * master key material
8403994a7c9SMaxim Levitsky      */
8413994a7c9SMaxim Levitsky     cipher = qcrypto_cipher_new(luks->cipher_alg,
8423994a7c9SMaxim Levitsky                                 luks->cipher_mode,
8433994a7c9SMaxim Levitsky                                 slotkey, luks->header.master_key_len,
8443994a7c9SMaxim Levitsky                                 errp);
8453994a7c9SMaxim Levitsky     if (!cipher) {
8463994a7c9SMaxim Levitsky         goto cleanup;
8473994a7c9SMaxim Levitsky     }
8483994a7c9SMaxim Levitsky 
8493994a7c9SMaxim Levitsky     ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
8503994a7c9SMaxim Levitsky                               luks->ivgen_cipher_alg,
8513994a7c9SMaxim Levitsky                               luks->ivgen_hash_alg,
8523994a7c9SMaxim Levitsky                               slotkey, luks->header.master_key_len,
8533994a7c9SMaxim Levitsky                               errp);
8543994a7c9SMaxim Levitsky     if (!ivgen) {
8553994a7c9SMaxim Levitsky         goto cleanup;
8563994a7c9SMaxim Levitsky     }
8573994a7c9SMaxim Levitsky 
8583994a7c9SMaxim Levitsky     /*
8593994a7c9SMaxim Levitsky      * Before storing the master key, we need to vastly
8603994a7c9SMaxim Levitsky      * increase its size, as protection against forensic
8613994a7c9SMaxim Levitsky      * disk data recovery
8623994a7c9SMaxim Levitsky      */
8633994a7c9SMaxim Levitsky     splitkey = g_new0(uint8_t, splitkeylen);
8643994a7c9SMaxim Levitsky 
8653994a7c9SMaxim Levitsky     if (qcrypto_afsplit_encode(luks->hash_alg,
8663994a7c9SMaxim Levitsky                                luks->header.master_key_len,
8673994a7c9SMaxim Levitsky                                slot->stripes,
8683994a7c9SMaxim Levitsky                                masterkey,
8693994a7c9SMaxim Levitsky                                splitkey,
8703994a7c9SMaxim Levitsky                                errp) < 0) {
8713994a7c9SMaxim Levitsky         goto cleanup;
8723994a7c9SMaxim Levitsky     }
8733994a7c9SMaxim Levitsky 
8743994a7c9SMaxim Levitsky     /*
8753994a7c9SMaxim Levitsky      * Now we encrypt the split master key with the key generated
8763994a7c9SMaxim Levitsky      * from the user's password, before storing it
8773994a7c9SMaxim Levitsky      */
8783994a7c9SMaxim Levitsky     if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
8793994a7c9SMaxim Levitsky                                             QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
8803994a7c9SMaxim Levitsky                                             0,
8813994a7c9SMaxim Levitsky                                             splitkey,
8823994a7c9SMaxim Levitsky                                             splitkeylen,
8833994a7c9SMaxim Levitsky                                             errp) < 0) {
8843994a7c9SMaxim Levitsky         goto cleanup;
8853994a7c9SMaxim Levitsky     }
8863994a7c9SMaxim Levitsky 
8873994a7c9SMaxim Levitsky     /* Write out the slot's master key material. */
8883994a7c9SMaxim Levitsky     if (writefunc(block,
8893994a7c9SMaxim Levitsky                   slot->key_offset_sector *
8903994a7c9SMaxim Levitsky                   QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
8913994a7c9SMaxim Levitsky                   splitkey, splitkeylen,
8923994a7c9SMaxim Levitsky                   opaque,
893757dda54SAlberto Faria                   errp) < 0) {
8943994a7c9SMaxim Levitsky         goto cleanup;
8953994a7c9SMaxim Levitsky     }
8963994a7c9SMaxim Levitsky 
8973994a7c9SMaxim Levitsky     slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
8983994a7c9SMaxim Levitsky 
8993994a7c9SMaxim Levitsky     if (qcrypto_block_luks_store_header(block,  writefunc, opaque, errp) < 0) {
9003994a7c9SMaxim Levitsky         goto cleanup;
9013994a7c9SMaxim Levitsky     }
9023994a7c9SMaxim Levitsky 
9033994a7c9SMaxim Levitsky     ret = 0;
9043994a7c9SMaxim Levitsky 
9053994a7c9SMaxim Levitsky cleanup:
9063994a7c9SMaxim Levitsky     if (slotkey) {
9073994a7c9SMaxim Levitsky         memset(slotkey, 0, luks->header.master_key_len);
9083994a7c9SMaxim Levitsky     }
9093994a7c9SMaxim Levitsky     if (splitkey) {
9103994a7c9SMaxim Levitsky         memset(splitkey, 0, splitkeylen);
9113994a7c9SMaxim Levitsky     }
9123994a7c9SMaxim Levitsky     return ret;
9133994a7c9SMaxim Levitsky }
9143994a7c9SMaxim Levitsky 
9153994a7c9SMaxim Levitsky /*
9163e308f20SDaniel P. Berrange  * Given a key slot, and user password, this will attempt to unlock
9173e308f20SDaniel P. Berrange  * the master encryption key from the key slot.
9183e308f20SDaniel P. Berrange  *
9193e308f20SDaniel P. Berrange  * Returns:
9203e308f20SDaniel P. Berrange  *    0 if the key slot is disabled, or key could not be decrypted
9213e308f20SDaniel P. Berrange  *      with the provided password
9223e308f20SDaniel P. Berrange  *    1 if the key slot is enabled, and key decrypted successfully
9233e308f20SDaniel P. Berrange  *      with the provided password
9243e308f20SDaniel P. Berrange  *   -1 if a fatal error occurred loading the key
9253e308f20SDaniel P. Berrange  */
9263e308f20SDaniel P. Berrange static int
9273e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block,
9287e60a6f5SMaxim Levitsky                             size_t slot_idx,
9293e308f20SDaniel P. Berrange                             const char *password,
9303e308f20SDaniel P. Berrange                             uint8_t *masterkey,
9313e308f20SDaniel P. Berrange                             QCryptoBlockReadFunc readfunc,
9323e308f20SDaniel P. Berrange                             void *opaque,
9333e308f20SDaniel P. Berrange                             Error **errp)
9343e308f20SDaniel P. Berrange {
9353e308f20SDaniel P. Berrange     QCryptoBlockLUKS *luks = block->opaque;
936557d2bdcSMaxim Levitsky     const QCryptoBlockLUKSKeySlot *slot;
93757b9f113SDaniel P. Berrangé     g_autofree uint8_t *splitkey = NULL;
9383e308f20SDaniel P. Berrange     size_t splitkeylen;
93957b9f113SDaniel P. Berrangé     g_autofree uint8_t *possiblekey = NULL;
940757dda54SAlberto Faria     int rv;
94157b9f113SDaniel P. Berrangé     g_autoptr(QCryptoCipher) cipher = NULL;
9423e308f20SDaniel P. Berrange     uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
94357b9f113SDaniel P. Berrangé     g_autoptr(QCryptoIVGen) ivgen = NULL;
9443e308f20SDaniel P. Berrange     size_t niv;
9453e308f20SDaniel P. Berrange 
946557d2bdcSMaxim Levitsky     assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
947557d2bdcSMaxim Levitsky     slot = &luks->header.key_slots[slot_idx];
9483e308f20SDaniel P. Berrange     if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
9493e308f20SDaniel P. Berrange         return 0;
9503e308f20SDaniel P. Berrange     }
9513e308f20SDaniel P. Berrange 
9521ddd52e4SMaxim Levitsky     splitkeylen = luks->header.master_key_len * slot->stripes;
9533e308f20SDaniel P. Berrange     splitkey = g_new0(uint8_t, splitkeylen);
9541ddd52e4SMaxim Levitsky     possiblekey = g_new0(uint8_t, luks->header.master_key_len);
9553e308f20SDaniel P. Berrange 
9563e308f20SDaniel P. Berrange     /*
9573e308f20SDaniel P. Berrange      * The user password is used to generate a (possible)
9583e308f20SDaniel P. Berrange      * decryption key. This may or may not successfully
9593e308f20SDaniel P. Berrange      * decrypt the master key - we just blindly assume
9603e308f20SDaniel P. Berrange      * the key is correct and validate the results of
9613e308f20SDaniel P. Berrange      * decryption later.
9623e308f20SDaniel P. Berrange      */
9639d80e59dSMaxim Levitsky     if (qcrypto_pbkdf2(luks->hash_alg,
9643e308f20SDaniel P. Berrange                        (const uint8_t *)password, strlen(password),
9653e308f20SDaniel P. Berrange                        slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN,
9663e308f20SDaniel P. Berrange                        slot->iterations,
9671ddd52e4SMaxim Levitsky                        possiblekey, luks->header.master_key_len,
9683e308f20SDaniel P. Berrange                        errp) < 0) {
96957b9f113SDaniel P. Berrangé         return -1;
9703e308f20SDaniel P. Berrange     }
9713e308f20SDaniel P. Berrange 
9723e308f20SDaniel P. Berrange     /*
9733e308f20SDaniel P. Berrange      * We need to read the master key material from the
9743e308f20SDaniel P. Berrange      * LUKS key material header. What we're reading is
9753e308f20SDaniel P. Berrange      * not the raw master key, but rather the data after
9763e308f20SDaniel P. Berrange      * it has been passed through AFSplit and the result
9773e308f20SDaniel P. Berrange      * then encrypted.
9783e308f20SDaniel P. Berrange      */
9793e308f20SDaniel P. Berrange     rv = readfunc(block,
980f0d3c362SMaxim Levitsky                   slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
9813e308f20SDaniel P. Berrange                   splitkey, splitkeylen,
982e4a3507eSDaniel P. Berrange                   opaque,
98337509233SFam Zheng                   errp);
9843e308f20SDaniel P. Berrange     if (rv < 0) {
98557b9f113SDaniel P. Berrangé         return -1;
9863e308f20SDaniel P. Berrange     }
9873e308f20SDaniel P. Berrange 
9883e308f20SDaniel P. Berrange 
9893e308f20SDaniel P. Berrange     /* Setup the cipher/ivgen that we'll use to try to decrypt
9903e308f20SDaniel P. Berrange      * the split master key material */
9919d80e59dSMaxim Levitsky     cipher = qcrypto_cipher_new(luks->cipher_alg,
9929d80e59dSMaxim Levitsky                                 luks->cipher_mode,
9939d80e59dSMaxim Levitsky                                 possiblekey,
9949d80e59dSMaxim Levitsky                                 luks->header.master_key_len,
9953e308f20SDaniel P. Berrange                                 errp);
9963e308f20SDaniel P. Berrange     if (!cipher) {
99757b9f113SDaniel P. Berrangé         return -1;
9983e308f20SDaniel P. Berrange     }
9993e308f20SDaniel P. Berrange 
10009d80e59dSMaxim Levitsky     niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
10019d80e59dSMaxim Levitsky                                     luks->cipher_mode);
10029d80e59dSMaxim Levitsky 
10039d80e59dSMaxim Levitsky     ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
10049d80e59dSMaxim Levitsky                               luks->ivgen_cipher_alg,
10059d80e59dSMaxim Levitsky                               luks->ivgen_hash_alg,
10069d80e59dSMaxim Levitsky                               possiblekey,
10079d80e59dSMaxim Levitsky                               luks->header.master_key_len,
10083e308f20SDaniel P. Berrange                               errp);
10093e308f20SDaniel P. Berrange     if (!ivgen) {
101057b9f113SDaniel P. Berrangé         return -1;
10113e308f20SDaniel P. Berrange     }
10123e308f20SDaniel P. Berrange 
10133e308f20SDaniel P. Berrange 
10143e308f20SDaniel P. Berrange     /*
10153e308f20SDaniel P. Berrange      * The master key needs to be decrypted in the same
10163e308f20SDaniel P. Berrange      * way that the block device payload will be decrypted
10173e308f20SDaniel P. Berrange      * later. In particular we'll be using the IV generator
10183e308f20SDaniel P. Berrange      * to reset the encryption cipher every time the master
10193e308f20SDaniel P. Berrange      * key crosses a sector boundary.
10203e308f20SDaniel P. Berrange      */
10210270417cSVladimir Sementsov-Ogievskiy     if (qcrypto_block_cipher_decrypt_helper(cipher,
10223e308f20SDaniel P. Berrange                                             niv,
10233e308f20SDaniel P. Berrange                                             ivgen,
10243e308f20SDaniel P. Berrange                                             QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
10253e308f20SDaniel P. Berrange                                             0,
10263e308f20SDaniel P. Berrange                                             splitkey,
10273e308f20SDaniel P. Berrange                                             splitkeylen,
10283e308f20SDaniel P. Berrange                                             errp) < 0) {
102957b9f113SDaniel P. Berrangé         return -1;
10303e308f20SDaniel P. Berrange     }
10313e308f20SDaniel P. Berrange 
10323e308f20SDaniel P. Berrange     /*
10333e308f20SDaniel P. Berrange      * Now we've decrypted the split master key, join
10343e308f20SDaniel P. Berrange      * it back together to get the actual master key.
10353e308f20SDaniel P. Berrange      */
10369d80e59dSMaxim Levitsky     if (qcrypto_afsplit_decode(luks->hash_alg,
10371ddd52e4SMaxim Levitsky                                luks->header.master_key_len,
10383e308f20SDaniel P. Berrange                                slot->stripes,
10393e308f20SDaniel P. Berrange                                splitkey,
10403e308f20SDaniel P. Berrange                                masterkey,
10413e308f20SDaniel P. Berrange                                errp) < 0) {
104257b9f113SDaniel P. Berrangé         return -1;
10433e308f20SDaniel P. Berrange     }
10443e308f20SDaniel P. Berrange 
10453e308f20SDaniel P. Berrange 
10463e308f20SDaniel P. Berrange     /*
10473e308f20SDaniel P. Berrange      * We still don't know that the masterkey we got is valid,
10483e308f20SDaniel P. Berrange      * because we just blindly assumed the user's password
10493e308f20SDaniel P. Berrange      * was correct. This is where we now verify it. We are
10503e308f20SDaniel P. Berrange      * creating a hash of the master key using PBKDF and
10513e308f20SDaniel P. Berrange      * then comparing that to the hash stored in the key slot
10523e308f20SDaniel P. Berrange      * header
10533e308f20SDaniel P. Berrange      */
10549d80e59dSMaxim Levitsky     if (qcrypto_pbkdf2(luks->hash_alg,
10551ddd52e4SMaxim Levitsky                        masterkey,
10561ddd52e4SMaxim Levitsky                        luks->header.master_key_len,
10573e308f20SDaniel P. Berrange                        luks->header.master_key_salt,
10583e308f20SDaniel P. Berrange                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
10593e308f20SDaniel P. Berrange                        luks->header.master_key_iterations,
10601ddd52e4SMaxim Levitsky                        keydigest,
10611ddd52e4SMaxim Levitsky                        G_N_ELEMENTS(keydigest),
10623e308f20SDaniel P. Berrange                        errp) < 0) {
106357b9f113SDaniel P. Berrangé         return -1;
10643e308f20SDaniel P. Berrange     }
10653e308f20SDaniel P. Berrange 
10663e308f20SDaniel P. Berrange     if (memcmp(keydigest, luks->header.master_key_digest,
10673e308f20SDaniel P. Berrange                QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) {
10683e308f20SDaniel P. Berrange         /* Success, we got the right master key */
106957b9f113SDaniel P. Berrangé         return 1;
10703e308f20SDaniel P. Berrange     }
10713e308f20SDaniel P. Berrange 
10723e308f20SDaniel P. Berrange     /* Fail, user's password was not valid for this key slot,
10733e308f20SDaniel P. Berrange      * tell caller to try another slot */
107457b9f113SDaniel P. Berrangé     return 0;
10753e308f20SDaniel P. Berrange }
10763e308f20SDaniel P. Berrange 
10773e308f20SDaniel P. Berrange 
10783e308f20SDaniel P. Berrange /*
10793e308f20SDaniel P. Berrange  * Given a user password, this will iterate over all key
10803e308f20SDaniel P. Berrange  * slots and try to unlock each active key slot using the
10813e308f20SDaniel P. Berrange  * password until it successfully obtains a master key.
10823e308f20SDaniel P. Berrange  *
10833e308f20SDaniel P. Berrange  * Returns 0 if a key was loaded, -1 if no keys could be loaded
10843e308f20SDaniel P. Berrange  */
10853e308f20SDaniel P. Berrange static int
10863e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block,
10873e308f20SDaniel P. Berrange                             const char *password,
10881ddd52e4SMaxim Levitsky                             uint8_t *masterkey,
10893e308f20SDaniel P. Berrange                             QCryptoBlockReadFunc readfunc,
10903e308f20SDaniel P. Berrange                             void *opaque,
10913e308f20SDaniel P. Berrange                             Error **errp)
10923e308f20SDaniel P. Berrange {
10933e308f20SDaniel P. Berrange     size_t i;
10943e308f20SDaniel P. Berrange     int rv;
10953e308f20SDaniel P. Berrange 
10963e308f20SDaniel P. Berrange     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
10973e308f20SDaniel P. Berrange         rv = qcrypto_block_luks_load_key(block,
10987e60a6f5SMaxim Levitsky                                          i,
10993e308f20SDaniel P. Berrange                                          password,
11001ddd52e4SMaxim Levitsky                                          masterkey,
11013e308f20SDaniel P. Berrange                                          readfunc,
11023e308f20SDaniel P. Berrange                                          opaque,
11033e308f20SDaniel P. Berrange                                          errp);
11043e308f20SDaniel P. Berrange         if (rv < 0) {
11053e308f20SDaniel P. Berrange             goto error;
11063e308f20SDaniel P. Berrange         }
11073e308f20SDaniel P. Berrange         if (rv == 1) {
11083e308f20SDaniel P. Berrange             return 0;
11093e308f20SDaniel P. Berrange         }
11103e308f20SDaniel P. Berrange     }
11113e308f20SDaniel P. Berrange 
11123e308f20SDaniel P. Berrange     error_setg(errp, "Invalid password, cannot unlock any keyslot");
11133e308f20SDaniel P. Berrange  error:
11143e308f20SDaniel P. Berrange     return -1;
11153e308f20SDaniel P. Berrange }
11163e308f20SDaniel P. Berrange 
1117557d2bdcSMaxim Levitsky /*
1118557d2bdcSMaxim Levitsky  * Returns true if a slot i is marked as active
1119557d2bdcSMaxim Levitsky  * (contains encrypted copy of the master key)
1120557d2bdcSMaxim Levitsky  */
1121557d2bdcSMaxim Levitsky static bool
1122557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks,
1123557d2bdcSMaxim Levitsky                                unsigned int slot_idx)
1124557d2bdcSMaxim Levitsky {
1125557d2bdcSMaxim Levitsky     uint32_t val;
1126557d2bdcSMaxim Levitsky 
1127557d2bdcSMaxim Levitsky     assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
1128557d2bdcSMaxim Levitsky     val = luks->header.key_slots[slot_idx].active;
1129557d2bdcSMaxim Levitsky     return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
1130557d2bdcSMaxim Levitsky }
1131557d2bdcSMaxim Levitsky 
1132557d2bdcSMaxim Levitsky /*
1133557d2bdcSMaxim Levitsky  * Returns the number of slots that are marked as active
1134557d2bdcSMaxim Levitsky  * (slots that contain encrypted copy of the master key)
1135557d2bdcSMaxim Levitsky  */
1136557d2bdcSMaxim Levitsky static unsigned int
1137557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks)
1138557d2bdcSMaxim Levitsky {
1139557d2bdcSMaxim Levitsky     size_t i = 0;
1140557d2bdcSMaxim Levitsky     unsigned int ret = 0;
1141557d2bdcSMaxim Levitsky 
1142557d2bdcSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1143557d2bdcSMaxim Levitsky         if (qcrypto_block_luks_slot_active(luks, i)) {
1144557d2bdcSMaxim Levitsky             ret++;
1145557d2bdcSMaxim Levitsky         }
1146557d2bdcSMaxim Levitsky     }
1147557d2bdcSMaxim Levitsky     return ret;
1148557d2bdcSMaxim Levitsky }
1149557d2bdcSMaxim Levitsky 
1150557d2bdcSMaxim Levitsky /*
1151557d2bdcSMaxim Levitsky  * Finds first key slot which is not active
1152557d2bdcSMaxim Levitsky  * Returns the key slot index, or -1 if it doesn't exist
1153557d2bdcSMaxim Levitsky  */
1154557d2bdcSMaxim Levitsky static int
1155557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks)
1156557d2bdcSMaxim Levitsky {
1157557d2bdcSMaxim Levitsky     size_t i;
1158557d2bdcSMaxim Levitsky 
1159557d2bdcSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1160557d2bdcSMaxim Levitsky         if (!qcrypto_block_luks_slot_active(luks, i)) {
1161557d2bdcSMaxim Levitsky             return i;
1162557d2bdcSMaxim Levitsky         }
1163557d2bdcSMaxim Levitsky     }
1164557d2bdcSMaxim Levitsky     return -1;
1165557d2bdcSMaxim Levitsky }
1166557d2bdcSMaxim Levitsky 
1167557d2bdcSMaxim Levitsky /*
1168557d2bdcSMaxim Levitsky  * Erases an keyslot given its index
1169557d2bdcSMaxim Levitsky  * Returns:
1170557d2bdcSMaxim Levitsky  *    0 if the keyslot was erased successfully
1171557d2bdcSMaxim Levitsky  *   -1 if a error occurred while erasing the keyslot
1172557d2bdcSMaxim Levitsky  *
1173557d2bdcSMaxim Levitsky  */
1174557d2bdcSMaxim Levitsky static int
1175557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block,
1176557d2bdcSMaxim Levitsky                              unsigned int slot_idx,
1177557d2bdcSMaxim Levitsky                              QCryptoBlockWriteFunc writefunc,
1178557d2bdcSMaxim Levitsky                              void *opaque,
1179557d2bdcSMaxim Levitsky                              Error **errp)
1180557d2bdcSMaxim Levitsky {
1181557d2bdcSMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
1182557d2bdcSMaxim Levitsky     QCryptoBlockLUKSKeySlot *slot;
1183557d2bdcSMaxim Levitsky     g_autofree uint8_t *garbagesplitkey = NULL;
1184557d2bdcSMaxim Levitsky     size_t splitkeylen;
1185557d2bdcSMaxim Levitsky     size_t i;
1186557d2bdcSMaxim Levitsky     Error *local_err = NULL;
1187557d2bdcSMaxim Levitsky     int ret;
1188557d2bdcSMaxim Levitsky 
1189557d2bdcSMaxim Levitsky     assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
1190557d2bdcSMaxim Levitsky     slot = &luks->header.key_slots[slot_idx];
1191557d2bdcSMaxim Levitsky 
1192557d2bdcSMaxim Levitsky     splitkeylen = luks->header.master_key_len * slot->stripes;
1193557d2bdcSMaxim Levitsky     assert(splitkeylen > 0);
1194557d2bdcSMaxim Levitsky 
1195557d2bdcSMaxim Levitsky     garbagesplitkey = g_new0(uint8_t, splitkeylen);
1196557d2bdcSMaxim Levitsky 
1197557d2bdcSMaxim Levitsky     /* Reset the key slot header */
1198557d2bdcSMaxim Levitsky     memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN);
1199557d2bdcSMaxim Levitsky     slot->iterations = 0;
1200557d2bdcSMaxim Levitsky     slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
1201557d2bdcSMaxim Levitsky 
1202557d2bdcSMaxim Levitsky     ret = qcrypto_block_luks_store_header(block, writefunc,
1203557d2bdcSMaxim Levitsky                                           opaque, &local_err);
1204557d2bdcSMaxim Levitsky 
1205557d2bdcSMaxim Levitsky     if (ret < 0) {
1206557d2bdcSMaxim Levitsky         error_propagate(errp, local_err);
1207557d2bdcSMaxim Levitsky     }
1208557d2bdcSMaxim Levitsky     /*
1209557d2bdcSMaxim Levitsky      * Now try to erase the key material, even if the header
1210557d2bdcSMaxim Levitsky      * update failed
1211557d2bdcSMaxim Levitsky      */
1212557d2bdcSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) {
1213557d2bdcSMaxim Levitsky         if (qcrypto_random_bytes(garbagesplitkey,
1214557d2bdcSMaxim Levitsky                                  splitkeylen, &local_err) < 0) {
1215557d2bdcSMaxim Levitsky             /*
1216557d2bdcSMaxim Levitsky              * If we failed to get the random data, still write
1217557d2bdcSMaxim Levitsky              * at least zeros to the key slot at least once
1218557d2bdcSMaxim Levitsky              */
1219557d2bdcSMaxim Levitsky             error_propagate(errp, local_err);
1220557d2bdcSMaxim Levitsky 
1221557d2bdcSMaxim Levitsky             if (i > 0) {
1222557d2bdcSMaxim Levitsky                 return -1;
1223557d2bdcSMaxim Levitsky             }
1224557d2bdcSMaxim Levitsky         }
1225557d2bdcSMaxim Levitsky         if (writefunc(block,
1226557d2bdcSMaxim Levitsky                       slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
1227557d2bdcSMaxim Levitsky                       garbagesplitkey,
1228557d2bdcSMaxim Levitsky                       splitkeylen,
1229557d2bdcSMaxim Levitsky                       opaque,
1230757dda54SAlberto Faria                       &local_err) < 0) {
1231557d2bdcSMaxim Levitsky             error_propagate(errp, local_err);
1232557d2bdcSMaxim Levitsky             return -1;
1233557d2bdcSMaxim Levitsky         }
1234557d2bdcSMaxim Levitsky     }
1235557d2bdcSMaxim Levitsky     return ret;
1236557d2bdcSMaxim Levitsky }
12373e308f20SDaniel P. Berrange 
12383e308f20SDaniel P. Berrange static int
12393e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block,
12403e308f20SDaniel P. Berrange                         QCryptoBlockOpenOptions *options,
12411cd9a787SDaniel P. Berrange                         const char *optprefix,
12423e308f20SDaniel P. Berrange                         QCryptoBlockReadFunc readfunc,
12433e308f20SDaniel P. Berrange                         void *opaque,
12443e308f20SDaniel P. Berrange                         unsigned int flags,
1245c972fa12SVladimir Sementsov-Ogievskiy                         size_t n_threads,
12463e308f20SDaniel P. Berrange                         Error **errp)
12473e308f20SDaniel P. Berrange {
12489d80e59dSMaxim Levitsky     QCryptoBlockLUKS *luks = NULL;
124957b9f113SDaniel P. Berrangé     g_autofree uint8_t *masterkey = NULL;
125057b9f113SDaniel P. Berrangé     g_autofree char *password = NULL;
12513e308f20SDaniel P. Berrange 
12523e308f20SDaniel P. Berrange     if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
12533e308f20SDaniel P. Berrange         if (!options->u.luks.key_secret) {
12541cd9a787SDaniel P. Berrange             error_setg(errp, "Parameter '%skey-secret' is required for cipher",
12551cd9a787SDaniel P. Berrange                        optprefix ? optprefix : "");
12563e308f20SDaniel P. Berrange             return -1;
12573e308f20SDaniel P. Berrange         }
12583e308f20SDaniel P. Berrange         password = qcrypto_secret_lookup_as_utf8(
12593e308f20SDaniel P. Berrange             options->u.luks.key_secret, errp);
12603e308f20SDaniel P. Berrange         if (!password) {
12613e308f20SDaniel P. Berrange             return -1;
12623e308f20SDaniel P. Berrange         }
12633e308f20SDaniel P. Berrange     }
12643e308f20SDaniel P. Berrange 
12653e308f20SDaniel P. Berrange     luks = g_new0(QCryptoBlockLUKS, 1);
12663e308f20SDaniel P. Berrange     block->opaque = luks;
1267557d2bdcSMaxim Levitsky     luks->secret = g_strdup(options->u.luks.key_secret);
12683e308f20SDaniel P. Berrange 
1269dde2c5afSMaxim Levitsky     if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) {
12703e308f20SDaniel P. Berrange         goto fail;
12713e308f20SDaniel P. Berrange     }
12723e308f20SDaniel P. Berrange 
12739fa9c1c2SMaxim Levitsky     if (qcrypto_block_luks_check_header(luks, errp) < 0) {
12743e308f20SDaniel P. Berrange         goto fail;
12753e308f20SDaniel P. Berrange     }
12763e308f20SDaniel P. Berrange 
12779fa9c1c2SMaxim Levitsky     if (qcrypto_block_luks_parse_header(luks, errp) < 0) {
12783e308f20SDaniel P. Berrange         goto fail;
12793e308f20SDaniel P. Berrange     }
12803e308f20SDaniel P. Berrange 
12813e308f20SDaniel P. Berrange     if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
12823e308f20SDaniel P. Berrange         /* Try to find which key slot our password is valid for
12833e308f20SDaniel P. Berrange          * and unlock the master key from that slot.
12843e308f20SDaniel P. Berrange          */
12851ddd52e4SMaxim Levitsky 
12861ddd52e4SMaxim Levitsky         masterkey = g_new0(uint8_t, luks->header.master_key_len);
12871ddd52e4SMaxim Levitsky 
12883e308f20SDaniel P. Berrange         if (qcrypto_block_luks_find_key(block,
12893e308f20SDaniel P. Berrange                                         password,
12901ddd52e4SMaxim Levitsky                                         masterkey,
12913e308f20SDaniel P. Berrange                                         readfunc, opaque,
12923e308f20SDaniel P. Berrange                                         errp) < 0) {
12933e308f20SDaniel P. Berrange             goto fail;
12943e308f20SDaniel P. Berrange         }
12953e308f20SDaniel P. Berrange 
12963e308f20SDaniel P. Berrange         /* We have a valid master key now, so can setup the
12973e308f20SDaniel P. Berrange          * block device payload decryption objects
12983e308f20SDaniel P. Berrange          */
12999d80e59dSMaxim Levitsky         block->kdfhash = luks->hash_alg;
13009d80e59dSMaxim Levitsky         block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
13019d80e59dSMaxim Levitsky                                                luks->cipher_mode);
13029d80e59dSMaxim Levitsky 
13039d80e59dSMaxim Levitsky         block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
13049d80e59dSMaxim Levitsky                                          luks->ivgen_cipher_alg,
13059d80e59dSMaxim Levitsky                                          luks->ivgen_hash_alg,
13061ddd52e4SMaxim Levitsky                                          masterkey,
13071ddd52e4SMaxim Levitsky                                          luks->header.master_key_len,
13083e308f20SDaniel P. Berrange                                          errp);
13093e308f20SDaniel P. Berrange         if (!block->ivgen) {
13103e308f20SDaniel P. Berrange             goto fail;
13113e308f20SDaniel P. Berrange         }
13123e308f20SDaniel P. Berrange 
131361dd8a9aSMaxim Levitsky         if (qcrypto_block_init_cipher(block,
13149d80e59dSMaxim Levitsky                                       luks->cipher_alg,
13159d80e59dSMaxim Levitsky                                       luks->cipher_mode,
13161ddd52e4SMaxim Levitsky                                       masterkey,
13171ddd52e4SMaxim Levitsky                                       luks->header.master_key_len,
13181ddd52e4SMaxim Levitsky                                       n_threads,
131961dd8a9aSMaxim Levitsky                                       errp) < 0) {
13203e308f20SDaniel P. Berrange             goto fail;
13213e308f20SDaniel P. Berrange         }
13223e308f20SDaniel P. Berrange     }
13233e308f20SDaniel P. Berrange 
1324850f49deSDaniel P. Berrange     block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
1325f0d3c362SMaxim Levitsky     block->payload_offset = luks->header.payload_offset_sector *
1326850f49deSDaniel P. Berrange         block->sector_size;
13273e308f20SDaniel P. Berrange 
13283e308f20SDaniel P. Berrange     return 0;
13293e308f20SDaniel P. Berrange 
13303e308f20SDaniel P. Berrange  fail:
1331c972fa12SVladimir Sementsov-Ogievskiy     qcrypto_block_free_cipher(block);
13323e308f20SDaniel P. Berrange     qcrypto_ivgen_free(block->ivgen);
1333557d2bdcSMaxim Levitsky     g_free(luks->secret);
13343e308f20SDaniel P. Berrange     g_free(luks);
133561dd8a9aSMaxim Levitsky     return -1;
13363e308f20SDaniel P. Berrange }
13373e308f20SDaniel P. Berrange 
13383e308f20SDaniel P. Berrange 
13392ef950f9SFam Zheng static void
13402ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
13413e308f20SDaniel P. Berrange {
13422ef950f9SFam Zheng     QemuUUID uuid;
13432ef950f9SFam Zheng     qemu_uuid_generate(&uuid);
13442ef950f9SFam Zheng     qemu_uuid_unparse(&uuid, (char *)uuidstr);
13453e308f20SDaniel P. Berrange }
13463e308f20SDaniel P. Berrange 
13473e308f20SDaniel P. Berrange static int
13483e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block,
13493e308f20SDaniel P. Berrange                           QCryptoBlockCreateOptions *options,
13501cd9a787SDaniel P. Berrange                           const char *optprefix,
13513e308f20SDaniel P. Berrange                           QCryptoBlockInitFunc initfunc,
13523e308f20SDaniel P. Berrange                           QCryptoBlockWriteFunc writefunc,
13533e308f20SDaniel P. Berrange                           void *opaque,
13543e308f20SDaniel P. Berrange                           Error **errp)
13553e308f20SDaniel P. Berrange {
13563e308f20SDaniel P. Berrange     QCryptoBlockLUKS *luks;
13573e308f20SDaniel P. Berrange     QCryptoBlockCreateOptionsLUKS luks_opts;
13583e308f20SDaniel P. Berrange     Error *local_err = NULL;
135957b9f113SDaniel P. Berrangé     g_autofree uint8_t *masterkey = NULL;
1360bd56a55aSMaxim Levitsky     size_t header_sectors;
1361bd56a55aSMaxim Levitsky     size_t split_key_sectors;
13623e308f20SDaniel P. Berrange     size_t i;
136357b9f113SDaniel P. Berrangé     g_autofree char *password = NULL;
13643e308f20SDaniel P. Berrange     const char *cipher_alg;
13653e308f20SDaniel P. Berrange     const char *cipher_mode;
13663e308f20SDaniel P. Berrange     const char *ivgen_alg;
13673e308f20SDaniel P. Berrange     const char *ivgen_hash_alg = NULL;
13683e308f20SDaniel P. Berrange     const char *hash_alg;
136957b9f113SDaniel P. Berrangé     g_autofree char *cipher_mode_spec = NULL;
137059b060beSDaniel P. Berrange     uint64_t iters;
13713e308f20SDaniel P. Berrange 
13723e308f20SDaniel P. Berrange     memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
13733bd18890SDaniel P. Berrange     if (!luks_opts.has_iter_time) {
1374557d2bdcSMaxim Levitsky         luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
13753bd18890SDaniel P. Berrange     }
13763e308f20SDaniel P. Berrange     if (!luks_opts.has_cipher_alg) {
13773e308f20SDaniel P. Berrange         luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
13783e308f20SDaniel P. Berrange     }
13793e308f20SDaniel P. Berrange     if (!luks_opts.has_cipher_mode) {
13803e308f20SDaniel P. Berrange         luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS;
13813e308f20SDaniel P. Berrange     }
13823e308f20SDaniel P. Berrange     if (!luks_opts.has_ivgen_alg) {
13833e308f20SDaniel P. Berrange         luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64;
13843e308f20SDaniel P. Berrange     }
13853e308f20SDaniel P. Berrange     if (!luks_opts.has_hash_alg) {
13863e308f20SDaniel P. Berrange         luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256;
13873e308f20SDaniel P. Berrange     }
13888b7cdba3SDaniel P. Berrange     if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
13898b7cdba3SDaniel P. Berrange         if (!luks_opts.has_ivgen_hash_alg) {
13908b7cdba3SDaniel P. Berrange             luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256;
13918b7cdba3SDaniel P. Berrange             luks_opts.has_ivgen_hash_alg = true;
13928b7cdba3SDaniel P. Berrange         }
13938b7cdba3SDaniel P. Berrange     }
13949d80e59dSMaxim Levitsky 
13959d80e59dSMaxim Levitsky     luks = g_new0(QCryptoBlockLUKS, 1);
13969d80e59dSMaxim Levitsky     block->opaque = luks;
13979d80e59dSMaxim Levitsky 
13989d80e59dSMaxim Levitsky     luks->cipher_alg = luks_opts.cipher_alg;
13999d80e59dSMaxim Levitsky     luks->cipher_mode = luks_opts.cipher_mode;
14009d80e59dSMaxim Levitsky     luks->ivgen_alg = luks_opts.ivgen_alg;
14019d80e59dSMaxim Levitsky     luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
14029d80e59dSMaxim Levitsky     luks->hash_alg = luks_opts.hash_alg;
14039d80e59dSMaxim Levitsky 
14049d80e59dSMaxim Levitsky 
14058b7cdba3SDaniel P. Berrange     /* Note we're allowing ivgen_hash_alg to be set even for
14068b7cdba3SDaniel P. Berrange      * non-essiv iv generators that don't need a hash. It will
14078b7cdba3SDaniel P. Berrange      * be silently ignored, for compatibility with dm-crypt */
14083e308f20SDaniel P. Berrange 
14093e308f20SDaniel P. Berrange     if (!options->u.luks.key_secret) {
14101cd9a787SDaniel P. Berrange         error_setg(errp, "Parameter '%skey-secret' is required for cipher",
14111cd9a787SDaniel P. Berrange                    optprefix ? optprefix : "");
14129d80e59dSMaxim Levitsky         goto error;
14133e308f20SDaniel P. Berrange     }
1414557d2bdcSMaxim Levitsky     luks->secret = g_strdup(options->u.luks.key_secret);
1415557d2bdcSMaxim Levitsky 
14163e308f20SDaniel P. Berrange     password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
14173e308f20SDaniel P. Berrange     if (!password) {
14189d80e59dSMaxim Levitsky         goto error;
14193e308f20SDaniel P. Berrange     }
14203e308f20SDaniel P. Berrange 
14213e308f20SDaniel P. Berrange 
14223e308f20SDaniel P. Berrange     memcpy(luks->header.magic, qcrypto_block_luks_magic,
14233e308f20SDaniel P. Berrange            QCRYPTO_BLOCK_LUKS_MAGIC_LEN);
14243e308f20SDaniel P. Berrange 
14253e308f20SDaniel P. Berrange     /* We populate the header in native endianness initially and
14263e308f20SDaniel P. Berrange      * then convert everything to big endian just before writing
14273e308f20SDaniel P. Berrange      * it out to disk
14283e308f20SDaniel P. Berrange      */
14293e308f20SDaniel P. Berrange     luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION;
14302ef950f9SFam Zheng     qcrypto_block_luks_uuid_gen(luks->header.uuid);
14313e308f20SDaniel P. Berrange 
14323e308f20SDaniel P. Berrange     cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg,
14333e308f20SDaniel P. Berrange                                                       errp);
14343e308f20SDaniel P. Berrange     if (!cipher_alg) {
14353e308f20SDaniel P. Berrange         goto error;
14363e308f20SDaniel P. Berrange     }
14373e308f20SDaniel P. Berrange 
1438977c736fSMarkus Armbruster     cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode);
1439977c736fSMarkus Armbruster     ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg);
14403e308f20SDaniel P. Berrange     if (luks_opts.has_ivgen_hash_alg) {
1441977c736fSMarkus Armbruster         ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg);
14423e308f20SDaniel P. Berrange         cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
14433e308f20SDaniel P. Berrange                                            ivgen_hash_alg);
14443e308f20SDaniel P. Berrange     } else {
14453e308f20SDaniel P. Berrange         cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
14463e308f20SDaniel P. Berrange     }
1447977c736fSMarkus Armbruster     hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg);
14483e308f20SDaniel P. Berrange 
14493e308f20SDaniel P. Berrange 
14503e308f20SDaniel P. Berrange     if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
14513e308f20SDaniel P. Berrange         error_setg(errp, "Cipher name '%s' is too long for LUKS header",
14523e308f20SDaniel P. Berrange                    cipher_alg);
14533e308f20SDaniel P. Berrange         goto error;
14543e308f20SDaniel P. Berrange     }
14553e308f20SDaniel P. Berrange     if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) {
14563e308f20SDaniel P. Berrange         error_setg(errp, "Cipher mode '%s' is too long for LUKS header",
14573e308f20SDaniel P. Berrange                    cipher_mode_spec);
14583e308f20SDaniel P. Berrange         goto error;
14593e308f20SDaniel P. Berrange     }
14603e308f20SDaniel P. Berrange     if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) {
14613e308f20SDaniel P. Berrange         error_setg(errp, "Hash name '%s' is too long for LUKS header",
14623e308f20SDaniel P. Berrange                    hash_alg);
14633e308f20SDaniel P. Berrange         goto error;
14643e308f20SDaniel P. Berrange     }
14653e308f20SDaniel P. Berrange 
14663e308f20SDaniel P. Berrange     if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
14679d80e59dSMaxim Levitsky         luks->ivgen_cipher_alg =
14689d80e59dSMaxim Levitsky                 qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg,
14693e308f20SDaniel P. Berrange                                                 luks_opts.ivgen_hash_alg,
14703e308f20SDaniel P. Berrange                                                 &local_err);
14713e308f20SDaniel P. Berrange         if (local_err) {
14723e308f20SDaniel P. Berrange             error_propagate(errp, local_err);
14733e308f20SDaniel P. Berrange             goto error;
14743e308f20SDaniel P. Berrange         }
14753e308f20SDaniel P. Berrange     } else {
14769d80e59dSMaxim Levitsky         luks->ivgen_cipher_alg = luks_opts.cipher_alg;
14773e308f20SDaniel P. Berrange     }
14783e308f20SDaniel P. Berrange 
14793e308f20SDaniel P. Berrange     strcpy(luks->header.cipher_name, cipher_alg);
14803e308f20SDaniel P. Berrange     strcpy(luks->header.cipher_mode, cipher_mode_spec);
14813e308f20SDaniel P. Berrange     strcpy(luks->header.hash_spec, hash_alg);
14823e308f20SDaniel P. Berrange 
1483f0d3c362SMaxim Levitsky     luks->header.master_key_len =
1484f0d3c362SMaxim Levitsky         qcrypto_cipher_get_key_len(luks_opts.cipher_alg);
1485f0d3c362SMaxim Levitsky 
14863e308f20SDaniel P. Berrange     if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) {
1487f0d3c362SMaxim Levitsky         luks->header.master_key_len *= 2;
14883e308f20SDaniel P. Berrange     }
14893e308f20SDaniel P. Berrange 
14903e308f20SDaniel P. Berrange     /* Generate the salt used for hashing the master key
14913e308f20SDaniel P. Berrange      * with PBKDF later
14923e308f20SDaniel P. Berrange      */
14933e308f20SDaniel P. Berrange     if (qcrypto_random_bytes(luks->header.master_key_salt,
14943e308f20SDaniel P. Berrange                              QCRYPTO_BLOCK_LUKS_SALT_LEN,
14953e308f20SDaniel P. Berrange                              errp) < 0) {
14963e308f20SDaniel P. Berrange         goto error;
14973e308f20SDaniel P. Berrange     }
14983e308f20SDaniel P. Berrange 
14993e308f20SDaniel P. Berrange     /* Generate random master key */
1500f0d3c362SMaxim Levitsky     masterkey = g_new0(uint8_t, luks->header.master_key_len);
15013e308f20SDaniel P. Berrange     if (qcrypto_random_bytes(masterkey,
1502f0d3c362SMaxim Levitsky                              luks->header.master_key_len, errp) < 0) {
15033e308f20SDaniel P. Berrange         goto error;
15043e308f20SDaniel P. Berrange     }
15053e308f20SDaniel P. Berrange 
15063e308f20SDaniel P. Berrange 
15073e308f20SDaniel P. Berrange     /* Setup the block device payload encryption objects */
1508c972fa12SVladimir Sementsov-Ogievskiy     if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
1509c972fa12SVladimir Sementsov-Ogievskiy                                   luks_opts.cipher_mode, masterkey,
1510f0d3c362SMaxim Levitsky                                   luks->header.master_key_len, 1, errp) < 0) {
15113e308f20SDaniel P. Berrange         goto error;
15123e308f20SDaniel P. Berrange     }
15133e308f20SDaniel P. Berrange 
15143e308f20SDaniel P. Berrange     block->kdfhash = luks_opts.hash_alg;
15153e308f20SDaniel P. Berrange     block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg,
15163e308f20SDaniel P. Berrange                                            luks_opts.cipher_mode);
15173e308f20SDaniel P. Berrange     block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg,
15189d80e59dSMaxim Levitsky                                      luks->ivgen_cipher_alg,
15193e308f20SDaniel P. Berrange                                      luks_opts.ivgen_hash_alg,
1520f0d3c362SMaxim Levitsky                                      masterkey, luks->header.master_key_len,
15213e308f20SDaniel P. Berrange                                      errp);
15223e308f20SDaniel P. Berrange 
15233e308f20SDaniel P. Berrange     if (!block->ivgen) {
15243e308f20SDaniel P. Berrange         goto error;
15253e308f20SDaniel P. Berrange     }
15263e308f20SDaniel P. Berrange 
15273e308f20SDaniel P. Berrange 
15283e308f20SDaniel P. Berrange     /* Determine how many iterations we need to hash the master
15293e308f20SDaniel P. Berrange      * key, in order to have 1 second of compute time used
15303e308f20SDaniel P. Berrange      */
153159b060beSDaniel P. Berrange     iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
1532f0d3c362SMaxim Levitsky                                        masterkey, luks->header.master_key_len,
15333e308f20SDaniel P. Berrange                                        luks->header.master_key_salt,
15343e308f20SDaniel P. Berrange                                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
1535e74aabcfSDaniel P. Berrange                                        QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
15363e308f20SDaniel P. Berrange                                        &local_err);
15373e308f20SDaniel P. Berrange     if (local_err) {
15383e308f20SDaniel P. Berrange         error_propagate(errp, local_err);
15393e308f20SDaniel P. Berrange         goto error;
15403e308f20SDaniel P. Berrange     }
15413e308f20SDaniel P. Berrange 
15423bd18890SDaniel P. Berrange     if (iters > (ULLONG_MAX / luks_opts.iter_time)) {
15433bd18890SDaniel P. Berrange         error_setg_errno(errp, ERANGE,
15443bd18890SDaniel P. Berrange                          "PBKDF iterations %llu too large to scale",
15453bd18890SDaniel P. Berrange                          (unsigned long long)iters);
15463bd18890SDaniel P. Berrange         goto error;
15473bd18890SDaniel P. Berrange     }
15483bd18890SDaniel P. Berrange 
15493bd18890SDaniel P. Berrange     /* iter_time was in millis, but count_iters reported for secs */
15503bd18890SDaniel P. Berrange     iters = iters * luks_opts.iter_time / 1000;
15513bd18890SDaniel P. Berrange 
15523e308f20SDaniel P. Berrange     /* Why /= 8 ?  That matches cryptsetup, but there's no
15533e308f20SDaniel P. Berrange      * explanation why they chose /= 8... Probably so that
15543e308f20SDaniel P. Berrange      * if all 8 keyslots are active we only spend 1 second
15553e308f20SDaniel P. Berrange      * in total time to check all keys */
155659b060beSDaniel P. Berrange     iters /= 8;
155759b060beSDaniel P. Berrange     if (iters > UINT32_MAX) {
155859b060beSDaniel P. Berrange         error_setg_errno(errp, ERANGE,
155959b060beSDaniel P. Berrange                          "PBKDF iterations %llu larger than %u",
156059b060beSDaniel P. Berrange                          (unsigned long long)iters, UINT32_MAX);
156159b060beSDaniel P. Berrange         goto error;
156259b060beSDaniel P. Berrange     }
156359b060beSDaniel P. Berrange     iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS);
156459b060beSDaniel P. Berrange     luks->header.master_key_iterations = iters;
15653e308f20SDaniel P. Berrange 
15663e308f20SDaniel P. Berrange     /* Hash the master key, saving the result in the LUKS
15673e308f20SDaniel P. Berrange      * header. This hash is used when opening the encrypted
15683e308f20SDaniel P. Berrange      * device to verify that the user password unlocked a
15693e308f20SDaniel P. Berrange      * valid master key
15703e308f20SDaniel P. Berrange      */
15713e308f20SDaniel P. Berrange     if (qcrypto_pbkdf2(luks_opts.hash_alg,
1572f0d3c362SMaxim Levitsky                        masterkey, luks->header.master_key_len,
15733e308f20SDaniel P. Berrange                        luks->header.master_key_salt,
15743e308f20SDaniel P. Berrange                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
15753e308f20SDaniel P. Berrange                        luks->header.master_key_iterations,
15763e308f20SDaniel P. Berrange                        luks->header.master_key_digest,
15773e308f20SDaniel P. Berrange                        QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
15783e308f20SDaniel P. Berrange                        errp) < 0) {
15793e308f20SDaniel P. Berrange         goto error;
15803e308f20SDaniel P. Berrange     }
15813e308f20SDaniel P. Berrange 
1582bd56a55aSMaxim Levitsky     /* start with the sector that follows the header*/
1583bd56a55aSMaxim Levitsky     header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
1584bd56a55aSMaxim Levitsky         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
15853e308f20SDaniel P. Berrange 
1586bd56a55aSMaxim Levitsky     split_key_sectors =
1587bd56a55aSMaxim Levitsky         qcrypto_block_luks_splitkeylen_sectors(luks,
1588bd56a55aSMaxim Levitsky                                                header_sectors,
1589bd56a55aSMaxim Levitsky                                                QCRYPTO_BLOCK_LUKS_STRIPES);
1590bd56a55aSMaxim Levitsky 
15913e308f20SDaniel P. Berrange     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1592bd56a55aSMaxim Levitsky         QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i];
1593bd56a55aSMaxim Levitsky         slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
15943e308f20SDaniel P. Berrange 
1595bd56a55aSMaxim Levitsky         slot->key_offset_sector = header_sectors + i * split_key_sectors;
1596bd56a55aSMaxim Levitsky         slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
15973e308f20SDaniel P. Berrange     }
15983e308f20SDaniel P. Berrange 
15993e308f20SDaniel P. Berrange     /* The total size of the LUKS headers is the partition header + key
16003e308f20SDaniel P. Berrange      * slot headers, rounded up to the nearest sector, combined with
16013e308f20SDaniel P. Berrange      * the size of each master key material region, also rounded up
16023e308f20SDaniel P. Berrange      * to the nearest sector */
1603bd56a55aSMaxim Levitsky     luks->header.payload_offset_sector = header_sectors +
1604bd56a55aSMaxim Levitsky             QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
16053e308f20SDaniel P. Berrange 
1606850f49deSDaniel P. Berrange     block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
1607f0d3c362SMaxim Levitsky     block->payload_offset = luks->header.payload_offset_sector *
1608850f49deSDaniel P. Berrange         block->sector_size;
16093e308f20SDaniel P. Berrange 
16103e308f20SDaniel P. Berrange     /* Reserve header space to match payload offset */
1611e4a3507eSDaniel P. Berrange     initfunc(block, block->payload_offset, opaque, &local_err);
16123e308f20SDaniel P. Berrange     if (local_err) {
16133e308f20SDaniel P. Berrange         error_propagate(errp, local_err);
16143e308f20SDaniel P. Berrange         goto error;
16153e308f20SDaniel P. Berrange     }
16163e308f20SDaniel P. Berrange 
16173e308f20SDaniel P. Berrange 
16183994a7c9SMaxim Levitsky     /* populate the slot 0 with the password encrypted master key*/
16193994a7c9SMaxim Levitsky     /* This will also store the header */
16203994a7c9SMaxim Levitsky     if (qcrypto_block_luks_store_key(block,
16213994a7c9SMaxim Levitsky                                      0,
16223994a7c9SMaxim Levitsky                                      password,
16233994a7c9SMaxim Levitsky                                      masterkey,
16243994a7c9SMaxim Levitsky                                      luks_opts.iter_time,
16253994a7c9SMaxim Levitsky                                      writefunc,
1626e4a3507eSDaniel P. Berrange                                      opaque,
16273994a7c9SMaxim Levitsky                                      errp) < 0) {
16283e308f20SDaniel P. Berrange         goto error;
16293e308f20SDaniel P. Berrange     }
16303e308f20SDaniel P. Berrange 
1631f0d3c362SMaxim Levitsky     memset(masterkey, 0, luks->header.master_key_len);
16323e308f20SDaniel P. Berrange 
16333e308f20SDaniel P. Berrange     return 0;
16343e308f20SDaniel P. Berrange 
16353e308f20SDaniel P. Berrange  error:
16363e308f20SDaniel P. Berrange     if (masterkey) {
1637f0d3c362SMaxim Levitsky         memset(masterkey, 0, luks->header.master_key_len);
16383e308f20SDaniel P. Berrange     }
16393e308f20SDaniel P. Berrange 
1640c972fa12SVladimir Sementsov-Ogievskiy     qcrypto_block_free_cipher(block);
1641b640adcaSVladimir Sementsov-Ogievskiy     qcrypto_ivgen_free(block->ivgen);
1642b640adcaSVladimir Sementsov-Ogievskiy 
1643557d2bdcSMaxim Levitsky     g_free(luks->secret);
16443e308f20SDaniel P. Berrange     g_free(luks);
16453e308f20SDaniel P. Berrange     return -1;
16463e308f20SDaniel P. Berrange }
16473e308f20SDaniel P. Berrange 
1648557d2bdcSMaxim Levitsky static int
1649557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block,
1650557d2bdcSMaxim Levitsky                                      QCryptoBlockReadFunc readfunc,
1651557d2bdcSMaxim Levitsky                                      QCryptoBlockWriteFunc writefunc,
1652557d2bdcSMaxim Levitsky                                      void *opaque,
1653557d2bdcSMaxim Levitsky                                      QCryptoBlockAmendOptionsLUKS *opts_luks,
1654557d2bdcSMaxim Levitsky                                      bool force,
1655557d2bdcSMaxim Levitsky                                      Error **errp)
1656557d2bdcSMaxim Levitsky {
1657557d2bdcSMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
1658557d2bdcSMaxim Levitsky     uint64_t iter_time = opts_luks->has_iter_time ?
1659557d2bdcSMaxim Levitsky                          opts_luks->iter_time :
1660557d2bdcSMaxim Levitsky                          QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
1661557d2bdcSMaxim Levitsky     int keyslot;
1662557d2bdcSMaxim Levitsky     g_autofree char *old_password = NULL;
1663557d2bdcSMaxim Levitsky     g_autofree char *new_password = NULL;
1664557d2bdcSMaxim Levitsky     g_autofree uint8_t *master_key = NULL;
1665557d2bdcSMaxim Levitsky 
1666557d2bdcSMaxim Levitsky     char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret;
1667557d2bdcSMaxim Levitsky 
1668557d2bdcSMaxim Levitsky     if (!opts_luks->has_new_secret) {
1669557d2bdcSMaxim Levitsky         error_setg(errp, "'new-secret' is required to activate a keyslot");
1670557d2bdcSMaxim Levitsky         return -1;
1671557d2bdcSMaxim Levitsky     }
1672557d2bdcSMaxim Levitsky     if (opts_luks->has_old_secret) {
1673557d2bdcSMaxim Levitsky         error_setg(errp,
1674557d2bdcSMaxim Levitsky                    "'old-secret' must not be given when activating keyslots");
1675557d2bdcSMaxim Levitsky         return -1;
1676557d2bdcSMaxim Levitsky     }
1677557d2bdcSMaxim Levitsky 
1678557d2bdcSMaxim Levitsky     if (opts_luks->has_keyslot) {
1679557d2bdcSMaxim Levitsky         keyslot = opts_luks->keyslot;
1680557d2bdcSMaxim Levitsky         if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
1681557d2bdcSMaxim Levitsky             error_setg(errp,
1682557d2bdcSMaxim Levitsky                        "Invalid keyslot %u specified, must be between 0 and %u",
1683557d2bdcSMaxim Levitsky                        keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
1684557d2bdcSMaxim Levitsky             return -1;
1685557d2bdcSMaxim Levitsky         }
1686557d2bdcSMaxim Levitsky     } else {
1687557d2bdcSMaxim Levitsky         keyslot = qcrypto_block_luks_find_free_keyslot(luks);
1688557d2bdcSMaxim Levitsky         if (keyslot == -1) {
1689557d2bdcSMaxim Levitsky             error_setg(errp,
1690557d2bdcSMaxim Levitsky                        "Can't add a keyslot - all keyslots are in use");
1691557d2bdcSMaxim Levitsky             return -1;
1692557d2bdcSMaxim Levitsky         }
1693557d2bdcSMaxim Levitsky     }
1694557d2bdcSMaxim Levitsky 
1695557d2bdcSMaxim Levitsky     if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) {
1696557d2bdcSMaxim Levitsky         error_setg(errp,
1697557d2bdcSMaxim Levitsky                    "Refusing to overwrite active keyslot %i - "
1698557d2bdcSMaxim Levitsky                    "please erase it first",
1699557d2bdcSMaxim Levitsky                    keyslot);
1700557d2bdcSMaxim Levitsky         return -1;
1701557d2bdcSMaxim Levitsky     }
1702557d2bdcSMaxim Levitsky 
1703557d2bdcSMaxim Levitsky     /* Locate the password that will be used to retrieve the master key */
1704557d2bdcSMaxim Levitsky     old_password = qcrypto_secret_lookup_as_utf8(secret, errp);
1705557d2bdcSMaxim Levitsky     if (!old_password) {
1706557d2bdcSMaxim Levitsky         return -1;
1707557d2bdcSMaxim Levitsky     }
1708557d2bdcSMaxim Levitsky 
1709557d2bdcSMaxim Levitsky     /* Retrieve the master key */
1710557d2bdcSMaxim Levitsky     master_key = g_new0(uint8_t, luks->header.master_key_len);
1711557d2bdcSMaxim Levitsky 
1712557d2bdcSMaxim Levitsky     if (qcrypto_block_luks_find_key(block, old_password, master_key,
1713557d2bdcSMaxim Levitsky                                     readfunc, opaque, errp) < 0) {
1714557d2bdcSMaxim Levitsky         error_append_hint(errp, "Failed to retrieve the master key");
1715557d2bdcSMaxim Levitsky         return -1;
1716557d2bdcSMaxim Levitsky     }
1717557d2bdcSMaxim Levitsky 
1718557d2bdcSMaxim Levitsky     /* Locate the new password*/
1719557d2bdcSMaxim Levitsky     new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp);
1720557d2bdcSMaxim Levitsky     if (!new_password) {
1721557d2bdcSMaxim Levitsky         return -1;
1722557d2bdcSMaxim Levitsky     }
1723557d2bdcSMaxim Levitsky 
1724557d2bdcSMaxim Levitsky     /* Now set the new keyslots */
1725557d2bdcSMaxim Levitsky     if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key,
1726557d2bdcSMaxim Levitsky                                      iter_time, writefunc, opaque, errp)) {
1727557d2bdcSMaxim Levitsky         error_append_hint(errp, "Failed to write to keyslot %i", keyslot);
1728557d2bdcSMaxim Levitsky         return -1;
1729557d2bdcSMaxim Levitsky     }
1730557d2bdcSMaxim Levitsky     return 0;
1731557d2bdcSMaxim Levitsky }
1732557d2bdcSMaxim Levitsky 
1733557d2bdcSMaxim Levitsky static int
1734557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block,
1735557d2bdcSMaxim Levitsky                                         QCryptoBlockReadFunc readfunc,
1736557d2bdcSMaxim Levitsky                                         QCryptoBlockWriteFunc writefunc,
1737557d2bdcSMaxim Levitsky                                         void *opaque,
1738557d2bdcSMaxim Levitsky                                         QCryptoBlockAmendOptionsLUKS *opts_luks,
1739557d2bdcSMaxim Levitsky                                         bool force,
1740557d2bdcSMaxim Levitsky                                         Error **errp)
1741557d2bdcSMaxim Levitsky {
1742557d2bdcSMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
1743557d2bdcSMaxim Levitsky     g_autofree uint8_t *tmpkey = NULL;
1744557d2bdcSMaxim Levitsky     g_autofree char *old_password = NULL;
1745557d2bdcSMaxim Levitsky 
1746557d2bdcSMaxim Levitsky     if (opts_luks->has_new_secret) {
1747557d2bdcSMaxim Levitsky         error_setg(errp,
1748557d2bdcSMaxim Levitsky                    "'new-secret' must not be given when erasing keyslots");
1749557d2bdcSMaxim Levitsky         return -1;
1750557d2bdcSMaxim Levitsky     }
1751557d2bdcSMaxim Levitsky     if (opts_luks->has_iter_time) {
1752557d2bdcSMaxim Levitsky         error_setg(errp,
1753557d2bdcSMaxim Levitsky                    "'iter-time' must not be given when erasing keyslots");
1754557d2bdcSMaxim Levitsky         return -1;
1755557d2bdcSMaxim Levitsky     }
1756557d2bdcSMaxim Levitsky     if (opts_luks->has_secret) {
1757557d2bdcSMaxim Levitsky         error_setg(errp,
1758557d2bdcSMaxim Levitsky                    "'secret' must not be given when erasing keyslots");
1759557d2bdcSMaxim Levitsky         return -1;
1760557d2bdcSMaxim Levitsky     }
1761557d2bdcSMaxim Levitsky 
1762557d2bdcSMaxim Levitsky     /* Load the old password if given */
1763557d2bdcSMaxim Levitsky     if (opts_luks->has_old_secret) {
1764557d2bdcSMaxim Levitsky         old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret,
1765557d2bdcSMaxim Levitsky                                                      errp);
1766557d2bdcSMaxim Levitsky         if (!old_password) {
1767557d2bdcSMaxim Levitsky             return -1;
1768557d2bdcSMaxim Levitsky         }
1769557d2bdcSMaxim Levitsky 
1770557d2bdcSMaxim Levitsky         /*
1771557d2bdcSMaxim Levitsky          * Allocate a temporary key buffer that we will need when
1772557d2bdcSMaxim Levitsky          * checking if slot matches the given old password
1773557d2bdcSMaxim Levitsky          */
1774557d2bdcSMaxim Levitsky         tmpkey = g_new0(uint8_t, luks->header.master_key_len);
1775557d2bdcSMaxim Levitsky     }
1776557d2bdcSMaxim Levitsky 
1777557d2bdcSMaxim Levitsky     /* Erase an explicitly given keyslot */
1778557d2bdcSMaxim Levitsky     if (opts_luks->has_keyslot) {
1779557d2bdcSMaxim Levitsky         int keyslot = opts_luks->keyslot;
1780557d2bdcSMaxim Levitsky 
1781557d2bdcSMaxim Levitsky         if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
1782557d2bdcSMaxim Levitsky             error_setg(errp,
1783557d2bdcSMaxim Levitsky                        "Invalid keyslot %i specified, must be between 0 and %i",
1784557d2bdcSMaxim Levitsky                        keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
1785557d2bdcSMaxim Levitsky             return -1;
1786557d2bdcSMaxim Levitsky         }
1787557d2bdcSMaxim Levitsky 
1788557d2bdcSMaxim Levitsky         if (opts_luks->has_old_secret) {
1789557d2bdcSMaxim Levitsky             int rv = qcrypto_block_luks_load_key(block,
1790557d2bdcSMaxim Levitsky                                                  keyslot,
1791557d2bdcSMaxim Levitsky                                                  old_password,
1792557d2bdcSMaxim Levitsky                                                  tmpkey,
1793557d2bdcSMaxim Levitsky                                                  readfunc,
1794557d2bdcSMaxim Levitsky                                                  opaque,
1795557d2bdcSMaxim Levitsky                                                  errp);
1796557d2bdcSMaxim Levitsky             if (rv == -1) {
1797557d2bdcSMaxim Levitsky                 return -1;
1798557d2bdcSMaxim Levitsky             } else if (rv == 0) {
1799557d2bdcSMaxim Levitsky                 error_setg(errp,
1800557d2bdcSMaxim Levitsky                            "Given keyslot %i doesn't contain the given "
1801557d2bdcSMaxim Levitsky                            "old password for erase operation",
1802557d2bdcSMaxim Levitsky                            keyslot);
1803557d2bdcSMaxim Levitsky                 return -1;
1804557d2bdcSMaxim Levitsky             }
1805557d2bdcSMaxim Levitsky         }
1806557d2bdcSMaxim Levitsky 
1807557d2bdcSMaxim Levitsky         if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) {
1808557d2bdcSMaxim Levitsky             error_setg(errp,
1809557d2bdcSMaxim Levitsky                        "Given keyslot %i is already erased (inactive) ",
1810557d2bdcSMaxim Levitsky                        keyslot);
1811557d2bdcSMaxim Levitsky             return -1;
1812557d2bdcSMaxim Levitsky         }
1813557d2bdcSMaxim Levitsky 
1814557d2bdcSMaxim Levitsky         if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) {
1815557d2bdcSMaxim Levitsky             error_setg(errp,
1816557d2bdcSMaxim Levitsky                        "Attempt to erase the only active keyslot %i "
1817557d2bdcSMaxim Levitsky                        "which will erase all the data in the image "
1818557d2bdcSMaxim Levitsky                        "irreversibly - refusing operation",
1819557d2bdcSMaxim Levitsky                        keyslot);
1820557d2bdcSMaxim Levitsky             return -1;
1821557d2bdcSMaxim Levitsky         }
1822557d2bdcSMaxim Levitsky 
1823557d2bdcSMaxim Levitsky         if (qcrypto_block_luks_erase_key(block, keyslot,
1824557d2bdcSMaxim Levitsky                                          writefunc, opaque, errp)) {
1825557d2bdcSMaxim Levitsky             error_append_hint(errp, "Failed to erase keyslot %i", keyslot);
1826557d2bdcSMaxim Levitsky             return -1;
1827557d2bdcSMaxim Levitsky         }
1828557d2bdcSMaxim Levitsky 
1829557d2bdcSMaxim Levitsky     /* Erase all keyslots that match the given old password */
1830557d2bdcSMaxim Levitsky     } else if (opts_luks->has_old_secret) {
1831557d2bdcSMaxim Levitsky 
1832557d2bdcSMaxim Levitsky         unsigned long slots_to_erase_bitmap = 0;
1833557d2bdcSMaxim Levitsky         size_t i;
1834557d2bdcSMaxim Levitsky         int slot_count;
1835557d2bdcSMaxim Levitsky 
1836557d2bdcSMaxim Levitsky         assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <=
1837557d2bdcSMaxim Levitsky                sizeof(slots_to_erase_bitmap) * 8);
1838557d2bdcSMaxim Levitsky 
1839557d2bdcSMaxim Levitsky         for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1840557d2bdcSMaxim Levitsky             int rv = qcrypto_block_luks_load_key(block,
1841557d2bdcSMaxim Levitsky                                                  i,
1842557d2bdcSMaxim Levitsky                                                  old_password,
1843557d2bdcSMaxim Levitsky                                                  tmpkey,
1844557d2bdcSMaxim Levitsky                                                  readfunc,
1845557d2bdcSMaxim Levitsky                                                  opaque,
1846557d2bdcSMaxim Levitsky                                                  errp);
1847557d2bdcSMaxim Levitsky             if (rv == -1) {
1848557d2bdcSMaxim Levitsky                 return -1;
1849557d2bdcSMaxim Levitsky             } else if (rv == 1) {
1850557d2bdcSMaxim Levitsky                 bitmap_set(&slots_to_erase_bitmap, i, 1);
1851557d2bdcSMaxim Levitsky             }
1852557d2bdcSMaxim Levitsky         }
1853557d2bdcSMaxim Levitsky 
1854557d2bdcSMaxim Levitsky         slot_count = bitmap_count_one(&slots_to_erase_bitmap,
1855557d2bdcSMaxim Levitsky                                       QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
1856557d2bdcSMaxim Levitsky         if (slot_count == 0) {
1857557d2bdcSMaxim Levitsky             error_setg(errp,
1858557d2bdcSMaxim Levitsky                        "No keyslots match given (old) password for erase operation");
1859557d2bdcSMaxim Levitsky             return -1;
1860557d2bdcSMaxim Levitsky         }
1861557d2bdcSMaxim Levitsky 
1862557d2bdcSMaxim Levitsky         if (!force &&
1863557d2bdcSMaxim Levitsky             slot_count == qcrypto_block_luks_count_active_slots(luks)) {
1864557d2bdcSMaxim Levitsky             error_setg(errp,
1865557d2bdcSMaxim Levitsky                        "All the active keyslots match the (old) password that "
1866557d2bdcSMaxim Levitsky                        "was given and erasing them will erase all the data in "
1867557d2bdcSMaxim Levitsky                        "the image irreversibly - refusing operation");
1868557d2bdcSMaxim Levitsky             return -1;
1869557d2bdcSMaxim Levitsky         }
1870557d2bdcSMaxim Levitsky 
1871557d2bdcSMaxim Levitsky         /* Now apply the update */
1872557d2bdcSMaxim Levitsky         for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1873557d2bdcSMaxim Levitsky             if (!test_bit(i, &slots_to_erase_bitmap)) {
1874557d2bdcSMaxim Levitsky                 continue;
1875557d2bdcSMaxim Levitsky             }
1876557d2bdcSMaxim Levitsky             if (qcrypto_block_luks_erase_key(block, i, writefunc,
1877557d2bdcSMaxim Levitsky                 opaque, errp)) {
1878557d2bdcSMaxim Levitsky                 error_append_hint(errp, "Failed to erase keyslot %zu", i);
1879557d2bdcSMaxim Levitsky                 return -1;
1880557d2bdcSMaxim Levitsky             }
1881557d2bdcSMaxim Levitsky         }
1882557d2bdcSMaxim Levitsky     } else {
1883557d2bdcSMaxim Levitsky         error_setg(errp,
1884557d2bdcSMaxim Levitsky                    "To erase keyslot(s), either explicit keyslot index "
1885557d2bdcSMaxim Levitsky                    "or the password currently contained in them must be given");
1886557d2bdcSMaxim Levitsky         return -1;
1887557d2bdcSMaxim Levitsky     }
1888557d2bdcSMaxim Levitsky     return 0;
1889557d2bdcSMaxim Levitsky }
1890557d2bdcSMaxim Levitsky 
1891557d2bdcSMaxim Levitsky static int
1892557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block,
1893557d2bdcSMaxim Levitsky                                  QCryptoBlockReadFunc readfunc,
1894557d2bdcSMaxim Levitsky                                  QCryptoBlockWriteFunc writefunc,
1895557d2bdcSMaxim Levitsky                                  void *opaque,
1896557d2bdcSMaxim Levitsky                                  QCryptoBlockAmendOptions *options,
1897557d2bdcSMaxim Levitsky                                  bool force,
1898557d2bdcSMaxim Levitsky                                  Error **errp)
1899557d2bdcSMaxim Levitsky {
1900557d2bdcSMaxim Levitsky     QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks;
1901557d2bdcSMaxim Levitsky 
1902557d2bdcSMaxim Levitsky     switch (opts_luks->state) {
1903557d2bdcSMaxim Levitsky     case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE:
1904557d2bdcSMaxim Levitsky         return qcrypto_block_luks_amend_add_keyslot(block, readfunc,
1905557d2bdcSMaxim Levitsky                                                     writefunc, opaque,
1906557d2bdcSMaxim Levitsky                                                     opts_luks, force, errp);
1907557d2bdcSMaxim Levitsky     case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE:
1908557d2bdcSMaxim Levitsky         return qcrypto_block_luks_amend_erase_keyslots(block, readfunc,
1909557d2bdcSMaxim Levitsky                                                        writefunc, opaque,
1910557d2bdcSMaxim Levitsky                                                        opts_luks, force, errp);
1911557d2bdcSMaxim Levitsky     default:
1912557d2bdcSMaxim Levitsky         g_assert_not_reached();
1913557d2bdcSMaxim Levitsky     }
1914557d2bdcSMaxim Levitsky }
19153e308f20SDaniel P. Berrange 
191640c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block,
191740c85028SDaniel P. Berrange                                        QCryptoBlockInfo *info,
191840c85028SDaniel P. Berrange                                        Error **errp)
191940c85028SDaniel P. Berrange {
192040c85028SDaniel P. Berrange     QCryptoBlockLUKS *luks = block->opaque;
192140c85028SDaniel P. Berrange     QCryptoBlockInfoLUKSSlot *slot;
1922c3033fd3SEric Blake     QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots;
192340c85028SDaniel P. Berrange     size_t i;
192440c85028SDaniel P. Berrange 
192540c85028SDaniel P. Berrange     info->u.luks.cipher_alg = luks->cipher_alg;
192640c85028SDaniel P. Berrange     info->u.luks.cipher_mode = luks->cipher_mode;
192740c85028SDaniel P. Berrange     info->u.luks.ivgen_alg = luks->ivgen_alg;
192840c85028SDaniel P. Berrange     if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
192940c85028SDaniel P. Berrange         info->u.luks.has_ivgen_hash_alg = true;
193040c85028SDaniel P. Berrange         info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg;
193140c85028SDaniel P. Berrange     }
193240c85028SDaniel P. Berrange     info->u.luks.hash_alg = luks->hash_alg;
193340c85028SDaniel P. Berrange     info->u.luks.payload_offset = block->payload_offset;
193440c85028SDaniel P. Berrange     info->u.luks.master_key_iters = luks->header.master_key_iterations;
193540c85028SDaniel P. Berrange     info->u.luks.uuid = g_strndup((const char *)luks->header.uuid,
193640c85028SDaniel P. Berrange                                   sizeof(luks->header.uuid));
193740c85028SDaniel P. Berrange 
193840c85028SDaniel P. Berrange     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1939c3033fd3SEric Blake         slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
194040c85028SDaniel P. Berrange         slot->active = luks->header.key_slots[i].active ==
194140c85028SDaniel P. Berrange             QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
1942f0d3c362SMaxim Levitsky         slot->key_offset = luks->header.key_slots[i].key_offset_sector
194340c85028SDaniel P. Berrange              * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
194440c85028SDaniel P. Berrange         if (slot->active) {
194540c85028SDaniel P. Berrange             slot->has_iters = true;
194640c85028SDaniel P. Berrange             slot->iters = luks->header.key_slots[i].iterations;
194740c85028SDaniel P. Berrange             slot->has_stripes = true;
194840c85028SDaniel P. Berrange             slot->stripes = luks->header.key_slots[i].stripes;
194940c85028SDaniel P. Berrange         }
195040c85028SDaniel P. Berrange 
1951c3033fd3SEric Blake         QAPI_LIST_APPEND(tail, slot);
195240c85028SDaniel P. Berrange     }
195340c85028SDaniel P. Berrange 
195440c85028SDaniel P. Berrange     return 0;
195540c85028SDaniel P. Berrange }
195640c85028SDaniel P. Berrange 
195740c85028SDaniel P. Berrange 
19583e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
19593e308f20SDaniel P. Berrange {
1960557d2bdcSMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
1961557d2bdcSMaxim Levitsky     if (luks) {
1962557d2bdcSMaxim Levitsky         g_free(luks->secret);
1963557d2bdcSMaxim Levitsky         g_free(luks);
1964557d2bdcSMaxim Levitsky     }
19653e308f20SDaniel P. Berrange }
19663e308f20SDaniel P. Berrange 
19673e308f20SDaniel P. Berrange 
19683e308f20SDaniel P. Berrange static int
19693e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block,
19704609742aSDaniel P. Berrange                            uint64_t offset,
19713e308f20SDaniel P. Berrange                            uint8_t *buf,
19723e308f20SDaniel P. Berrange                            size_t len,
19733e308f20SDaniel P. Berrange                            Error **errp)
19743e308f20SDaniel P. Berrange {
19754609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19764609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19770f0d596cSVladimir Sementsov-Ogievskiy     return qcrypto_block_decrypt_helper(block,
19783e308f20SDaniel P. Berrange                                         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
19794609742aSDaniel P. Berrange                                         offset, buf, len, errp);
19803e308f20SDaniel P. Berrange }
19813e308f20SDaniel P. Berrange 
19823e308f20SDaniel P. Berrange 
19833e308f20SDaniel P. Berrange static int
19843e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block,
19854609742aSDaniel P. Berrange                            uint64_t offset,
19863e308f20SDaniel P. Berrange                            uint8_t *buf,
19873e308f20SDaniel P. Berrange                            size_t len,
19883e308f20SDaniel P. Berrange                            Error **errp)
19893e308f20SDaniel P. Berrange {
19904609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19914609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19920f0d596cSVladimir Sementsov-Ogievskiy     return qcrypto_block_encrypt_helper(block,
19933e308f20SDaniel P. Berrange                                         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
19944609742aSDaniel P. Berrange                                         offset, buf, len, errp);
19953e308f20SDaniel P. Berrange }
19963e308f20SDaniel P. Berrange 
19973e308f20SDaniel P. Berrange 
19983e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = {
19993e308f20SDaniel P. Berrange     .open = qcrypto_block_luks_open,
20003e308f20SDaniel P. Berrange     .create = qcrypto_block_luks_create,
2001557d2bdcSMaxim Levitsky     .amend = qcrypto_block_luks_amend_options,
200240c85028SDaniel P. Berrange     .get_info = qcrypto_block_luks_get_info,
20033e308f20SDaniel P. Berrange     .cleanup = qcrypto_block_luks_cleanup,
20043e308f20SDaniel P. Berrange     .decrypt = qcrypto_block_luks_decrypt,
20053e308f20SDaniel P. Berrange     .encrypt = qcrypto_block_luks_encrypt,
20063e308f20SDaniel P. Berrange     .has_format = qcrypto_block_luks_has_format,
20073e308f20SDaniel P. Berrange };
2008