xref: /qemu/crypto/block-luks.c (revision befdba9e)
13e308f20SDaniel P. Berrange /*
23e308f20SDaniel P. Berrange  * QEMU Crypto block device encryption LUKS format
33e308f20SDaniel P. Berrange  *
43e308f20SDaniel P. Berrange  * Copyright (c) 2015-2016 Red Hat, Inc.
53e308f20SDaniel P. Berrange  *
63e308f20SDaniel P. Berrange  * This library is free software; you can redistribute it and/or
73e308f20SDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
83e308f20SDaniel P. Berrange  * License as published by the Free Software Foundation; either
9b7cbb874SThomas Huth  * version 2.1 of the License, or (at your option) any later version.
103e308f20SDaniel P. Berrange  *
113e308f20SDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
123e308f20SDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
133e308f20SDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
143e308f20SDaniel P. Berrange  * Lesser General Public License for more details.
153e308f20SDaniel P. Berrange  *
163e308f20SDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
173e308f20SDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
183e308f20SDaniel P. Berrange  *
193e308f20SDaniel P. Berrange  */
203e308f20SDaniel P. Berrange 
213e308f20SDaniel P. Berrange #include "qemu/osdep.h"
22da34e65cSMarkus Armbruster #include "qapi/error.h"
2358369e22SPaolo Bonzini #include "qemu/bswap.h"
243e308f20SDaniel P. Berrange 
25986bc8deSMichael S. Tsirkin #include "block-luks.h"
263e308f20SDaniel P. Berrange 
273e308f20SDaniel P. Berrange #include "crypto/hash.h"
283e308f20SDaniel P. Berrange #include "crypto/afsplit.h"
293e308f20SDaniel P. Berrange #include "crypto/pbkdf.h"
303e308f20SDaniel P. Berrange #include "crypto/secret.h"
313e308f20SDaniel P. Berrange #include "crypto/random.h"
322ef950f9SFam Zheng #include "qemu/uuid.h"
333e308f20SDaniel P. Berrange 
343e308f20SDaniel P. Berrange #include "qemu/coroutine.h"
353e308f20SDaniel P. Berrange 
363e308f20SDaniel P. Berrange /*
373e308f20SDaniel P. Berrange  * Reference for the LUKS format implemented here is
383e308f20SDaniel P. Berrange  *
393e308f20SDaniel P. Berrange  *   docs/on-disk-format.pdf
403e308f20SDaniel P. Berrange  *
413e308f20SDaniel P. Berrange  * in 'cryptsetup' package source code
423e308f20SDaniel P. Berrange  *
433e308f20SDaniel P. Berrange  * This file implements the 1.2.1 specification, dated
443e308f20SDaniel P. Berrange  * Oct 16, 2011.
453e308f20SDaniel P. Berrange  */
463e308f20SDaniel P. Berrange 
473e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS;
483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSHeader QCryptoBlockLUKSHeader;
493e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSKeySlot QCryptoBlockLUKSKeySlot;
503e308f20SDaniel P. Berrange 
513e308f20SDaniel P. Berrange 
523e308f20SDaniel P. Berrange /* The following constants are all defined by the LUKS spec */
533e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_VERSION 1
543e308f20SDaniel P. Berrange 
553e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MAGIC_LEN 6
563e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN 32
573e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN 32
583e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN 32
593e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_DIGEST_LEN 20
603e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SALT_LEN 32
613e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_UUID_LEN 40
623e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS 8
633e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_STRIPES 4000
643e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS 1000
653e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS 1000
663e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET 4096
673e308f20SDaniel P. Berrange 
683e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED 0x0000DEAD
693e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3
703e308f20SDaniel P. Berrange 
713e308f20SDaniel P. Berrange #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL
723e308f20SDaniel P. Berrange 
733e308f20SDaniel P. Berrange static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
743e308f20SDaniel P. Berrange     'L', 'U', 'K', 'S', 0xBA, 0xBE
753e308f20SDaniel P. Berrange };
763e308f20SDaniel P. Berrange 
773e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap;
783e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap {
793e308f20SDaniel P. Berrange     const char *name;
803e308f20SDaniel P. Berrange     int id;
813e308f20SDaniel P. Berrange };
823e308f20SDaniel P. Berrange 
833e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap;
843e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap {
853e308f20SDaniel P. Berrange     uint32_t key_bytes;
863e308f20SDaniel P. Berrange     int id;
873e308f20SDaniel P. Berrange };
883e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap;
893e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap {
903e308f20SDaniel P. Berrange     const char *name;
913e308f20SDaniel P. Berrange     const QCryptoBlockLUKSCipherSizeMap *sizes;
923e308f20SDaniel P. Berrange };
933e308f20SDaniel P. Berrange 
943e308f20SDaniel P. Berrange 
953e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
963e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = {
973e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_AES_128 },
983e308f20SDaniel P. Berrange     { 24, QCRYPTO_CIPHER_ALG_AES_192 },
993e308f20SDaniel P. Berrange     { 32, QCRYPTO_CIPHER_ALG_AES_256 },
1003e308f20SDaniel P. Berrange     { 0, 0 },
1013e308f20SDaniel P. Berrange };
1023e308f20SDaniel P. Berrange 
1033e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1043e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = {
1053e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_CAST5_128 },
1063e308f20SDaniel P. Berrange     { 0, 0 },
1073e308f20SDaniel P. Berrange };
1083e308f20SDaniel P. Berrange 
1093e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1103e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = {
1113e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 },
1123e308f20SDaniel P. Berrange     { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 },
1133e308f20SDaniel P. Berrange     { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 },
1143e308f20SDaniel P. Berrange     { 0, 0 },
1153e308f20SDaniel P. Berrange };
1163e308f20SDaniel P. Berrange 
1173e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
1183e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = {
1193e308f20SDaniel P. Berrange     { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 },
1203e308f20SDaniel P. Berrange     { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 },
1213e308f20SDaniel P. Berrange     { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 },
1223e308f20SDaniel P. Berrange     { 0, 0 },
1233e308f20SDaniel P. Berrange };
1243e308f20SDaniel P. Berrange 
1253e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap
1263e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = {
1273e308f20SDaniel P. Berrange     { "aes", qcrypto_block_luks_cipher_size_map_aes },
1283e308f20SDaniel P. Berrange     { "cast5", qcrypto_block_luks_cipher_size_map_cast5 },
1293e308f20SDaniel P. Berrange     { "serpent", qcrypto_block_luks_cipher_size_map_serpent },
1303e308f20SDaniel P. Berrange     { "twofish", qcrypto_block_luks_cipher_size_map_twofish },
1313e308f20SDaniel P. Berrange };
1323e308f20SDaniel P. Berrange 
1333e308f20SDaniel P. Berrange 
1343e308f20SDaniel P. Berrange /*
1353e308f20SDaniel P. Berrange  * This struct is written to disk in big-endian format,
1363e308f20SDaniel P. Berrange  * but operated upon in native-endian format.
1373e308f20SDaniel P. Berrange  */
1383e308f20SDaniel P. Berrange struct QCryptoBlockLUKSKeySlot {
1393e308f20SDaniel P. Berrange     /* state of keyslot, enabled/disable */
1403e308f20SDaniel P. Berrange     uint32_t active;
1413e308f20SDaniel P. Berrange     /* iterations for PBKDF2 */
1423e308f20SDaniel P. Berrange     uint32_t iterations;
1433e308f20SDaniel P. Berrange     /* salt for PBKDF2 */
1443e308f20SDaniel P. Berrange     uint8_t salt[QCRYPTO_BLOCK_LUKS_SALT_LEN];
1453e308f20SDaniel P. Berrange     /* start sector of key material */
146f0d3c362SMaxim Levitsky     uint32_t key_offset_sector;
1473e308f20SDaniel P. Berrange     /* number of anti-forensic stripes */
1483e308f20SDaniel P. Berrange     uint32_t stripes;
1495993e3beSGreg Kurz };
1503e308f20SDaniel P. Berrange 
1513e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
1523e308f20SDaniel P. Berrange 
1533e308f20SDaniel P. Berrange 
1543e308f20SDaniel P. Berrange /*
1553e308f20SDaniel P. Berrange  * This struct is written to disk in big-endian format,
1563e308f20SDaniel P. Berrange  * but operated upon in native-endian format.
1573e308f20SDaniel P. Berrange  */
1583e308f20SDaniel P. Berrange struct QCryptoBlockLUKSHeader {
1593e308f20SDaniel P. Berrange     /* 'L', 'U', 'K', 'S', '0xBA', '0xBE' */
1603e308f20SDaniel P. Berrange     char magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN];
1613e308f20SDaniel P. Berrange 
1623e308f20SDaniel P. Berrange     /* LUKS version, currently 1 */
1633e308f20SDaniel P. Berrange     uint16_t version;
1643e308f20SDaniel P. Berrange 
1653e308f20SDaniel P. Berrange     /* cipher name specification (aes, etc) */
1663e308f20SDaniel P. Berrange     char cipher_name[QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN];
1673e308f20SDaniel P. Berrange 
1683e308f20SDaniel P. Berrange     /* cipher mode specification (cbc-plain, xts-essiv:sha256, etc) */
1693e308f20SDaniel P. Berrange     char cipher_mode[QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN];
1703e308f20SDaniel P. Berrange 
1713e308f20SDaniel P. Berrange     /* hash specification (sha256, etc) */
1723e308f20SDaniel P. Berrange     char hash_spec[QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN];
1733e308f20SDaniel P. Berrange 
1743e308f20SDaniel P. Berrange     /* start offset of the volume data (in 512 byte sectors) */
175f0d3c362SMaxim Levitsky     uint32_t payload_offset_sector;
1763e308f20SDaniel P. Berrange 
1773e308f20SDaniel P. Berrange     /* Number of key bytes */
178f0d3c362SMaxim Levitsky     uint32_t master_key_len;
1793e308f20SDaniel P. Berrange 
1803e308f20SDaniel P. Berrange     /* master key checksum after PBKDF2 */
1813e308f20SDaniel P. Berrange     uint8_t master_key_digest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
1823e308f20SDaniel P. Berrange 
1833e308f20SDaniel P. Berrange     /* salt for master key PBKDF2 */
1843e308f20SDaniel P. Berrange     uint8_t master_key_salt[QCRYPTO_BLOCK_LUKS_SALT_LEN];
1853e308f20SDaniel P. Berrange 
1863e308f20SDaniel P. Berrange     /* iterations for master key PBKDF2 */
1873e308f20SDaniel P. Berrange     uint32_t master_key_iterations;
1883e308f20SDaniel P. Berrange 
1893e308f20SDaniel P. Berrange     /* UUID of the partition in standard ASCII representation */
1903e308f20SDaniel P. Berrange     uint8_t uuid[QCRYPTO_BLOCK_LUKS_UUID_LEN];
1913e308f20SDaniel P. Berrange 
1923e308f20SDaniel P. Berrange     /* key slots */
1933e308f20SDaniel P. Berrange     QCryptoBlockLUKSKeySlot key_slots[QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS];
1945993e3beSGreg Kurz };
1953e308f20SDaniel P. Berrange 
1963e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592);
1973e308f20SDaniel P. Berrange 
1983e308f20SDaniel P. Berrange 
1993e308f20SDaniel P. Berrange struct QCryptoBlockLUKS {
2003e308f20SDaniel P. Berrange     QCryptoBlockLUKSHeader header;
20140c85028SDaniel P. Berrange 
2029d80e59dSMaxim Levitsky     /* Main encryption algorithm used for encryption*/
20340c85028SDaniel P. Berrange     QCryptoCipherAlgorithm cipher_alg;
2049d80e59dSMaxim Levitsky 
2059d80e59dSMaxim Levitsky     /* Mode of encryption for the selected encryption algorithm */
20640c85028SDaniel P. Berrange     QCryptoCipherMode cipher_mode;
2079d80e59dSMaxim Levitsky 
2089d80e59dSMaxim Levitsky     /* Initialization vector generation algorithm */
20940c85028SDaniel P. Berrange     QCryptoIVGenAlgorithm ivgen_alg;
2109d80e59dSMaxim Levitsky 
2119d80e59dSMaxim Levitsky     /* Hash algorithm used for IV generation*/
21240c85028SDaniel P. Berrange     QCryptoHashAlgorithm ivgen_hash_alg;
2139d80e59dSMaxim Levitsky 
2149d80e59dSMaxim Levitsky     /*
2159d80e59dSMaxim Levitsky      * Encryption algorithm used for IV generation.
2169d80e59dSMaxim Levitsky      * Usually the same as main encryption algorithm
2179d80e59dSMaxim Levitsky      */
2189d80e59dSMaxim Levitsky     QCryptoCipherAlgorithm ivgen_cipher_alg;
2199d80e59dSMaxim Levitsky 
2209d80e59dSMaxim Levitsky     /* Hash algorithm used in pbkdf2 function */
22140c85028SDaniel P. Berrange     QCryptoHashAlgorithm hash_alg;
2223e308f20SDaniel P. Berrange };
2233e308f20SDaniel P. Berrange 
2243e308f20SDaniel P. Berrange 
2253e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name,
2263e308f20SDaniel P. Berrange                                                  QCryptoCipherMode mode,
2273e308f20SDaniel P. Berrange                                                  uint32_t key_bytes,
2283e308f20SDaniel P. Berrange                                                  Error **errp)
2293e308f20SDaniel P. Berrange {
2303e308f20SDaniel P. Berrange     const QCryptoBlockLUKSCipherNameMap *map =
2313e308f20SDaniel P. Berrange         qcrypto_block_luks_cipher_name_map;
2323e308f20SDaniel P. Berrange     size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map);
2333e308f20SDaniel P. Berrange     size_t i, j;
2343e308f20SDaniel P. Berrange 
2353e308f20SDaniel P. Berrange     if (mode == QCRYPTO_CIPHER_MODE_XTS) {
2363e308f20SDaniel P. Berrange         key_bytes /= 2;
2373e308f20SDaniel P. Berrange     }
2383e308f20SDaniel P. Berrange 
2393e308f20SDaniel P. Berrange     for (i = 0; i < maplen; i++) {
2403e308f20SDaniel P. Berrange         if (!g_str_equal(map[i].name, name)) {
2413e308f20SDaniel P. Berrange             continue;
2423e308f20SDaniel P. Berrange         }
2433e308f20SDaniel P. Berrange         for (j = 0; j < map[i].sizes[j].key_bytes; j++) {
2443e308f20SDaniel P. Berrange             if (map[i].sizes[j].key_bytes == key_bytes) {
2453e308f20SDaniel P. Berrange                 return map[i].sizes[j].id;
2463e308f20SDaniel P. Berrange             }
2473e308f20SDaniel P. Berrange         }
2483e308f20SDaniel P. Berrange     }
2493e308f20SDaniel P. Berrange 
2503e308f20SDaniel P. Berrange     error_setg(errp, "Algorithm %s with key size %d bytes not supported",
2513e308f20SDaniel P. Berrange                name, key_bytes);
2523e308f20SDaniel P. Berrange     return 0;
2533e308f20SDaniel P. Berrange }
2543e308f20SDaniel P. Berrange 
2553e308f20SDaniel P. Berrange static const char *
2563e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
2573e308f20SDaniel P. Berrange                                      Error **errp)
2583e308f20SDaniel P. Berrange {
2593e308f20SDaniel P. Berrange     const QCryptoBlockLUKSCipherNameMap *map =
2603e308f20SDaniel P. Berrange         qcrypto_block_luks_cipher_name_map;
2613e308f20SDaniel P. Berrange     size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map);
2623e308f20SDaniel P. Berrange     size_t i, j;
2633e308f20SDaniel P. Berrange     for (i = 0; i < maplen; i++) {
2643e308f20SDaniel P. Berrange         for (j = 0; j < map[i].sizes[j].key_bytes; j++) {
2653e308f20SDaniel P. Berrange             if (map[i].sizes[j].id == alg) {
2663e308f20SDaniel P. Berrange                 return map[i].name;
2673e308f20SDaniel P. Berrange             }
2683e308f20SDaniel P. Berrange         }
2693e308f20SDaniel P. Berrange     }
2703e308f20SDaniel P. Berrange 
2713e308f20SDaniel P. Berrange     error_setg(errp, "Algorithm '%s' not supported",
272977c736fSMarkus Armbruster                QCryptoCipherAlgorithm_str(alg));
2733e308f20SDaniel P. Berrange     return NULL;
2743e308f20SDaniel P. Berrange }
2753e308f20SDaniel P. Berrange 
2763e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can
2773e308f20SDaniel P. Berrange  * make that function emit a more friendly error message */
2783e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name,
279f7abe0ecSMarc-André Lureau                                           const QEnumLookup *map,
2803e308f20SDaniel P. Berrange                                           const char *type,
2813e308f20SDaniel P. Berrange                                           Error **errp)
2823e308f20SDaniel P. Berrange {
2839ae33079SMarkus Armbruster     int ret = qapi_enum_parse(map, name, -1, NULL);
2843e308f20SDaniel P. Berrange 
2859ae33079SMarkus Armbruster     if (ret < 0) {
2863e308f20SDaniel P. Berrange         error_setg(errp, "%s %s not supported", type, name);
2873e308f20SDaniel P. Berrange         return 0;
2883e308f20SDaniel P. Berrange     }
2899ae33079SMarkus Armbruster     return ret;
2909ae33079SMarkus Armbruster }
2913e308f20SDaniel P. Berrange 
2923e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp)               \
2933e308f20SDaniel P. Berrange     qcrypto_block_luks_name_lookup(name,                                \
294f7abe0ecSMarc-André Lureau                                    &QCryptoCipherMode_lookup,           \
2953e308f20SDaniel P. Berrange                                    "Cipher mode",                       \
2963e308f20SDaniel P. Berrange                                    errp)
2973e308f20SDaniel P. Berrange 
2983e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp)                 \
2993e308f20SDaniel P. Berrange     qcrypto_block_luks_name_lookup(name,                                \
300f7abe0ecSMarc-André Lureau                                    &QCryptoHashAlgorithm_lookup,        \
3013e308f20SDaniel P. Berrange                                    "Hash algorithm",                    \
3023e308f20SDaniel P. Berrange                                    errp)
3033e308f20SDaniel P. Berrange 
3043e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp)                \
3053e308f20SDaniel P. Berrange     qcrypto_block_luks_name_lookup(name,                                \
306f7abe0ecSMarc-André Lureau                                    &QCryptoIVGenAlgorithm_lookup,       \
3073e308f20SDaniel P. Berrange                                    "IV generator",                      \
3083e308f20SDaniel P. Berrange                                    errp)
3093e308f20SDaniel P. Berrange 
3103e308f20SDaniel P. Berrange 
3113e308f20SDaniel P. Berrange static bool
3123e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf,
3133e308f20SDaniel P. Berrange                               size_t buf_size)
3143e308f20SDaniel P. Berrange {
3153e308f20SDaniel P. Berrange     const QCryptoBlockLUKSHeader *luks_header = (const void *)buf;
3163e308f20SDaniel P. Berrange 
3173e308f20SDaniel P. Berrange     if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) &&
3183e308f20SDaniel P. Berrange         memcmp(luks_header->magic, qcrypto_block_luks_magic,
3193e308f20SDaniel P. Berrange                QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 &&
3203e308f20SDaniel P. Berrange         be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) {
3213e308f20SDaniel P. Berrange         return true;
3223e308f20SDaniel P. Berrange     } else {
3233e308f20SDaniel P. Berrange         return false;
3243e308f20SDaniel P. Berrange     }
3253e308f20SDaniel P. Berrange }
3263e308f20SDaniel P. Berrange 
3273e308f20SDaniel P. Berrange 
3283e308f20SDaniel P. Berrange /**
3293e308f20SDaniel P. Berrange  * Deal with a quirk of dm-crypt usage of ESSIV.
3303e308f20SDaniel P. Berrange  *
3313e308f20SDaniel P. Berrange  * When calculating ESSIV IVs, the cipher length used by ESSIV
3323e308f20SDaniel P. Berrange  * may be different from the cipher length used for the block
3333e308f20SDaniel P. Berrange  * encryption, becauses dm-crypt uses the hash digest length
3343e308f20SDaniel P. Berrange  * as the key size. ie, if you have AES 128 as the block cipher
3353e308f20SDaniel P. Berrange  * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as
3363e308f20SDaniel P. Berrange  * the cipher since that gets a key length matching the digest
3373e308f20SDaniel P. Berrange  * size, not AES 128 with truncated digest as might be imagined
3383e308f20SDaniel P. Berrange  */
3393e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm
3403e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,
3413e308f20SDaniel P. Berrange                                 QCryptoHashAlgorithm hash,
3423e308f20SDaniel P. Berrange                                 Error **errp)
3433e308f20SDaniel P. Berrange {
3443e308f20SDaniel P. Berrange     size_t digestlen = qcrypto_hash_digest_len(hash);
3453e308f20SDaniel P. Berrange     size_t keylen = qcrypto_cipher_get_key_len(cipher);
3463e308f20SDaniel P. Berrange     if (digestlen == keylen) {
3473e308f20SDaniel P. Berrange         return cipher;
3483e308f20SDaniel P. Berrange     }
3493e308f20SDaniel P. Berrange 
3503e308f20SDaniel P. Berrange     switch (cipher) {
3513e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_AES_128:
3523e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_AES_192:
3533e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_AES_256:
3543e308f20SDaniel P. Berrange         if (digestlen == qcrypto_cipher_get_key_len(
3553e308f20SDaniel P. Berrange                 QCRYPTO_CIPHER_ALG_AES_128)) {
3563e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_AES_128;
3573e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3583e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_AES_192)) {
3593e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_AES_192;
3603e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3613e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_AES_256)) {
3623e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_AES_256;
3633e308f20SDaniel P. Berrange         } else {
3643e308f20SDaniel P. Berrange             error_setg(errp, "No AES cipher with key size %zu available",
3653e308f20SDaniel P. Berrange                        digestlen);
3663e308f20SDaniel P. Berrange             return 0;
3673e308f20SDaniel P. Berrange         }
3683e308f20SDaniel P. Berrange         break;
3693e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_SERPENT_128:
3703e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_SERPENT_192:
3713e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_SERPENT_256:
3723e308f20SDaniel P. Berrange         if (digestlen == qcrypto_cipher_get_key_len(
3733e308f20SDaniel P. Berrange                 QCRYPTO_CIPHER_ALG_SERPENT_128)) {
3743e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_SERPENT_128;
3753e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3763e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_SERPENT_192)) {
3773e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_SERPENT_192;
3783e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3793e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_SERPENT_256)) {
3803e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_SERPENT_256;
3813e308f20SDaniel P. Berrange         } else {
3823e308f20SDaniel P. Berrange             error_setg(errp, "No Serpent cipher with key size %zu available",
3833e308f20SDaniel P. Berrange                        digestlen);
3843e308f20SDaniel P. Berrange             return 0;
3853e308f20SDaniel P. Berrange         }
3863e308f20SDaniel P. Berrange         break;
3873e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_TWOFISH_128:
3883e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_TWOFISH_192:
3893e308f20SDaniel P. Berrange     case QCRYPTO_CIPHER_ALG_TWOFISH_256:
3903e308f20SDaniel P. Berrange         if (digestlen == qcrypto_cipher_get_key_len(
3913e308f20SDaniel P. Berrange                 QCRYPTO_CIPHER_ALG_TWOFISH_128)) {
3923e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_TWOFISH_128;
3933e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3943e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_TWOFISH_192)) {
3953e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_TWOFISH_192;
3963e308f20SDaniel P. Berrange         } else if (digestlen == qcrypto_cipher_get_key_len(
3973e308f20SDaniel P. Berrange                        QCRYPTO_CIPHER_ALG_TWOFISH_256)) {
3983e308f20SDaniel P. Berrange             return QCRYPTO_CIPHER_ALG_TWOFISH_256;
3993e308f20SDaniel P. Berrange         } else {
4003e308f20SDaniel P. Berrange             error_setg(errp, "No Twofish cipher with key size %zu available",
4013e308f20SDaniel P. Berrange                        digestlen);
4023e308f20SDaniel P. Berrange             return 0;
4033e308f20SDaniel P. Berrange         }
4043e308f20SDaniel P. Berrange         break;
4053e308f20SDaniel P. Berrange     default:
4063e308f20SDaniel P. Berrange         error_setg(errp, "Cipher %s not supported with essiv",
407977c736fSMarkus Armbruster                    QCryptoCipherAlgorithm_str(cipher));
4083e308f20SDaniel P. Berrange         return 0;
4093e308f20SDaniel P. Berrange     }
4103e308f20SDaniel P. Berrange }
4113e308f20SDaniel P. Berrange 
4123e308f20SDaniel P. Berrange /*
413bd56a55aSMaxim Levitsky  * Returns number of sectors needed to store the key material
414bd56a55aSMaxim Levitsky  * given number of anti forensic stripes
415bd56a55aSMaxim Levitsky  */
416bd56a55aSMaxim Levitsky static int
417bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks,
418bd56a55aSMaxim Levitsky                                        unsigned int header_sectors,
419bd56a55aSMaxim Levitsky                                        unsigned int stripes)
420bd56a55aSMaxim Levitsky {
421bd56a55aSMaxim Levitsky     /*
422bd56a55aSMaxim Levitsky      * This calculation doesn't match that shown in the spec,
423bd56a55aSMaxim Levitsky      * but instead follows the cryptsetup implementation.
424bd56a55aSMaxim Levitsky      */
425bd56a55aSMaxim Levitsky 
426bd56a55aSMaxim Levitsky     size_t splitkeylen = luks->header.master_key_len * stripes;
427bd56a55aSMaxim Levitsky 
428bd56a55aSMaxim Levitsky     /* First align the key material size to block size*/
429bd56a55aSMaxim Levitsky     size_t splitkeylen_sectors =
430bd56a55aSMaxim Levitsky         DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE);
431bd56a55aSMaxim Levitsky 
432bd56a55aSMaxim Levitsky     /* Then also align the key material size to the size of the header */
433bd56a55aSMaxim Levitsky     return ROUND_UP(splitkeylen_sectors, header_sectors);
434bd56a55aSMaxim Levitsky }
435bd56a55aSMaxim Levitsky 
436bd56a55aSMaxim Levitsky /*
437dde2c5afSMaxim Levitsky  * Stores the main LUKS header, taking care of endianess
438dde2c5afSMaxim Levitsky  */
439dde2c5afSMaxim Levitsky static int
440dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block,
441dde2c5afSMaxim Levitsky                                 QCryptoBlockWriteFunc writefunc,
442dde2c5afSMaxim Levitsky                                 void *opaque,
443dde2c5afSMaxim Levitsky                                 Error **errp)
444dde2c5afSMaxim Levitsky {
445dde2c5afSMaxim Levitsky     const QCryptoBlockLUKS *luks = block->opaque;
446dde2c5afSMaxim Levitsky     Error *local_err = NULL;
447dde2c5afSMaxim Levitsky     size_t i;
448dde2c5afSMaxim Levitsky     g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL;
449dde2c5afSMaxim Levitsky 
450dde2c5afSMaxim Levitsky     /* Create a copy of the header */
451dde2c5afSMaxim Levitsky     hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1);
452dde2c5afSMaxim Levitsky     memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader));
453dde2c5afSMaxim Levitsky 
454dde2c5afSMaxim Levitsky     /*
455dde2c5afSMaxim Levitsky      * Everything on disk uses Big Endian (tm), so flip header fields
456dde2c5afSMaxim Levitsky      * before writing them
457dde2c5afSMaxim Levitsky      */
458dde2c5afSMaxim Levitsky     cpu_to_be16s(&hdr_copy->version);
459dde2c5afSMaxim Levitsky     cpu_to_be32s(&hdr_copy->payload_offset_sector);
460dde2c5afSMaxim Levitsky     cpu_to_be32s(&hdr_copy->master_key_len);
461dde2c5afSMaxim Levitsky     cpu_to_be32s(&hdr_copy->master_key_iterations);
462dde2c5afSMaxim Levitsky 
463dde2c5afSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
464dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].active);
465dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].iterations);
466dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].key_offset_sector);
467dde2c5afSMaxim Levitsky         cpu_to_be32s(&hdr_copy->key_slots[i].stripes);
468dde2c5afSMaxim Levitsky     }
469dde2c5afSMaxim Levitsky 
470dde2c5afSMaxim Levitsky     /* Write out the partition header and key slot headers */
471dde2c5afSMaxim Levitsky     writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy),
472dde2c5afSMaxim Levitsky               opaque, &local_err);
473dde2c5afSMaxim Levitsky 
474dde2c5afSMaxim Levitsky     if (local_err) {
475dde2c5afSMaxim Levitsky         error_propagate(errp, local_err);
476dde2c5afSMaxim Levitsky         return -1;
477dde2c5afSMaxim Levitsky     }
478dde2c5afSMaxim Levitsky     return 0;
479dde2c5afSMaxim Levitsky }
480dde2c5afSMaxim Levitsky 
481dde2c5afSMaxim Levitsky /*
482dde2c5afSMaxim Levitsky  * Loads the main LUKS header,and byteswaps it to native endianess
483dde2c5afSMaxim Levitsky  * And run basic sanity checks on it
484dde2c5afSMaxim Levitsky  */
485dde2c5afSMaxim Levitsky static int
486dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block,
487dde2c5afSMaxim Levitsky                                 QCryptoBlockReadFunc readfunc,
488dde2c5afSMaxim Levitsky                                 void *opaque,
489dde2c5afSMaxim Levitsky                                 Error **errp)
490dde2c5afSMaxim Levitsky {
491dde2c5afSMaxim Levitsky     ssize_t rv;
492dde2c5afSMaxim Levitsky     size_t i;
493dde2c5afSMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
494dde2c5afSMaxim Levitsky 
495dde2c5afSMaxim Levitsky     /*
496dde2c5afSMaxim Levitsky      * Read the entire LUKS header, minus the key material from
497dde2c5afSMaxim Levitsky      * the underlying device
498dde2c5afSMaxim Levitsky      */
499dde2c5afSMaxim Levitsky     rv = readfunc(block, 0,
500dde2c5afSMaxim Levitsky                   (uint8_t *)&luks->header,
501dde2c5afSMaxim Levitsky                   sizeof(luks->header),
502dde2c5afSMaxim Levitsky                   opaque,
503dde2c5afSMaxim Levitsky                   errp);
504dde2c5afSMaxim Levitsky     if (rv < 0) {
505dde2c5afSMaxim Levitsky         return rv;
506dde2c5afSMaxim Levitsky     }
507dde2c5afSMaxim Levitsky 
508dde2c5afSMaxim Levitsky     /*
509dde2c5afSMaxim Levitsky      * The header is always stored in big-endian format, so
510dde2c5afSMaxim Levitsky      * convert everything to native
511dde2c5afSMaxim Levitsky      */
512dde2c5afSMaxim Levitsky     be16_to_cpus(&luks->header.version);
513dde2c5afSMaxim Levitsky     be32_to_cpus(&luks->header.payload_offset_sector);
514dde2c5afSMaxim Levitsky     be32_to_cpus(&luks->header.master_key_len);
515dde2c5afSMaxim Levitsky     be32_to_cpus(&luks->header.master_key_iterations);
516dde2c5afSMaxim Levitsky 
517dde2c5afSMaxim Levitsky     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
518dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].active);
519dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].iterations);
520dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].key_offset_sector);
521dde2c5afSMaxim Levitsky         be32_to_cpus(&luks->header.key_slots[i].stripes);
522dde2c5afSMaxim Levitsky     }
523dde2c5afSMaxim Levitsky 
524dde2c5afSMaxim Levitsky     return 0;
525dde2c5afSMaxim Levitsky }
526dde2c5afSMaxim Levitsky 
527dde2c5afSMaxim Levitsky /*
5289fa9c1c2SMaxim Levitsky  * Does basic sanity checks on the LUKS header
5299fa9c1c2SMaxim Levitsky  */
5309fa9c1c2SMaxim Levitsky static int
5319fa9c1c2SMaxim Levitsky qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
5329fa9c1c2SMaxim Levitsky {
533*befdba9eSMaxim Levitsky     size_t i, j;
534*befdba9eSMaxim Levitsky 
535*befdba9eSMaxim Levitsky     unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
536*befdba9eSMaxim Levitsky         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
537*befdba9eSMaxim Levitsky 
5389fa9c1c2SMaxim Levitsky     if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
5399fa9c1c2SMaxim Levitsky                QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
5409fa9c1c2SMaxim Levitsky         error_setg(errp, "Volume is not in LUKS format");
5419fa9c1c2SMaxim Levitsky         return -1;
5429fa9c1c2SMaxim Levitsky     }
5439fa9c1c2SMaxim Levitsky 
5449fa9c1c2SMaxim Levitsky     if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) {
5459fa9c1c2SMaxim Levitsky         error_setg(errp, "LUKS version %" PRIu32 " is not supported",
5469fa9c1c2SMaxim Levitsky                    luks->header.version);
5479fa9c1c2SMaxim Levitsky         return -1;
5489fa9c1c2SMaxim Levitsky     }
549*befdba9eSMaxim Levitsky 
550*befdba9eSMaxim Levitsky     /* Check all keyslots for corruption  */
551*befdba9eSMaxim Levitsky     for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) {
552*befdba9eSMaxim Levitsky 
553*befdba9eSMaxim Levitsky         const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i];
554*befdba9eSMaxim Levitsky         unsigned int start1 = slot1->key_offset_sector;
555*befdba9eSMaxim Levitsky         unsigned int len1 =
556*befdba9eSMaxim Levitsky             qcrypto_block_luks_splitkeylen_sectors(luks,
557*befdba9eSMaxim Levitsky                                                    header_sectors,
558*befdba9eSMaxim Levitsky                                                    slot1->stripes);
559*befdba9eSMaxim Levitsky 
560*befdba9eSMaxim Levitsky         if (slot1->stripes == 0) {
561*befdba9eSMaxim Levitsky             error_setg(errp, "Keyslot %zu is corrupted (stripes == 0)", i);
562*befdba9eSMaxim Levitsky             return -1;
563*befdba9eSMaxim Levitsky         }
564*befdba9eSMaxim Levitsky 
565*befdba9eSMaxim Levitsky         if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED &&
566*befdba9eSMaxim Levitsky             slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
567*befdba9eSMaxim Levitsky             error_setg(errp,
568*befdba9eSMaxim Levitsky                        "Keyslot %zu state (active/disable) is corrupted", i);
569*befdba9eSMaxim Levitsky             return -1;
570*befdba9eSMaxim Levitsky         }
571*befdba9eSMaxim Levitsky 
572*befdba9eSMaxim Levitsky         if (start1 + len1 > luks->header.payload_offset_sector) {
573*befdba9eSMaxim Levitsky             error_setg(errp,
574*befdba9eSMaxim Levitsky                        "Keyslot %zu is overlapping with the encrypted payload",
575*befdba9eSMaxim Levitsky                        i);
576*befdba9eSMaxim Levitsky             return -1;
577*befdba9eSMaxim Levitsky         }
578*befdba9eSMaxim Levitsky 
579*befdba9eSMaxim Levitsky         for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) {
580*befdba9eSMaxim Levitsky             const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j];
581*befdba9eSMaxim Levitsky             unsigned int start2 = slot2->key_offset_sector;
582*befdba9eSMaxim Levitsky             unsigned int len2 =
583*befdba9eSMaxim Levitsky                 qcrypto_block_luks_splitkeylen_sectors(luks,
584*befdba9eSMaxim Levitsky                                                        header_sectors,
585*befdba9eSMaxim Levitsky                                                        slot2->stripes);
586*befdba9eSMaxim Levitsky 
587*befdba9eSMaxim Levitsky             if (start1 + len1 > start2 && start2 + len2 > start1) {
588*befdba9eSMaxim Levitsky                 error_setg(errp,
589*befdba9eSMaxim Levitsky                            "Keyslots %zu and %zu are overlapping in the header",
590*befdba9eSMaxim Levitsky                            i, j);
591*befdba9eSMaxim Levitsky                 return -1;
592*befdba9eSMaxim Levitsky             }
593*befdba9eSMaxim Levitsky         }
594*befdba9eSMaxim Levitsky 
595*befdba9eSMaxim Levitsky     }
5969fa9c1c2SMaxim Levitsky     return 0;
5979fa9c1c2SMaxim Levitsky }
5989fa9c1c2SMaxim Levitsky 
5999fa9c1c2SMaxim Levitsky /*
6009fa9c1c2SMaxim Levitsky  * Parses the crypto parameters that are stored in the LUKS header
6019fa9c1c2SMaxim Levitsky  */
6029fa9c1c2SMaxim Levitsky 
6039fa9c1c2SMaxim Levitsky static int
6049fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp)
6059fa9c1c2SMaxim Levitsky {
6069fa9c1c2SMaxim Levitsky     g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode);
6079fa9c1c2SMaxim Levitsky     char *ivgen_name, *ivhash_name;
6089fa9c1c2SMaxim Levitsky     Error *local_err = NULL;
6099fa9c1c2SMaxim Levitsky 
6109fa9c1c2SMaxim Levitsky     /*
6119fa9c1c2SMaxim Levitsky      * The cipher_mode header contains a string that we have
6129fa9c1c2SMaxim Levitsky      * to further parse, of the format
6139fa9c1c2SMaxim Levitsky      *
6149fa9c1c2SMaxim Levitsky      *    <cipher-mode>-<iv-generator>[:<iv-hash>]
6159fa9c1c2SMaxim Levitsky      *
6169fa9c1c2SMaxim Levitsky      * eg  cbc-essiv:sha256, cbc-plain64
6179fa9c1c2SMaxim Levitsky      */
6189fa9c1c2SMaxim Levitsky     ivgen_name = strchr(cipher_mode, '-');
6199fa9c1c2SMaxim Levitsky     if (!ivgen_name) {
6209fa9c1c2SMaxim Levitsky         error_setg(errp, "Unexpected cipher mode string format %s",
6219fa9c1c2SMaxim Levitsky                    luks->header.cipher_mode);
6229fa9c1c2SMaxim Levitsky         return -1;
6239fa9c1c2SMaxim Levitsky     }
6249fa9c1c2SMaxim Levitsky     *ivgen_name = '\0';
6259fa9c1c2SMaxim Levitsky     ivgen_name++;
6269fa9c1c2SMaxim Levitsky 
6279fa9c1c2SMaxim Levitsky     ivhash_name = strchr(ivgen_name, ':');
6289fa9c1c2SMaxim Levitsky     if (!ivhash_name) {
6299fa9c1c2SMaxim Levitsky         luks->ivgen_hash_alg = 0;
6309fa9c1c2SMaxim Levitsky     } else {
6319fa9c1c2SMaxim Levitsky         *ivhash_name = '\0';
6329fa9c1c2SMaxim Levitsky         ivhash_name++;
6339fa9c1c2SMaxim Levitsky 
6349fa9c1c2SMaxim Levitsky         luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name,
6359fa9c1c2SMaxim Levitsky                                                                    &local_err);
6369fa9c1c2SMaxim Levitsky         if (local_err) {
6379fa9c1c2SMaxim Levitsky             error_propagate(errp, local_err);
6389fa9c1c2SMaxim Levitsky             return -1;
6399fa9c1c2SMaxim Levitsky         }
6409fa9c1c2SMaxim Levitsky     }
6419fa9c1c2SMaxim Levitsky 
6429fa9c1c2SMaxim Levitsky     luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode,
6439fa9c1c2SMaxim Levitsky                                                               &local_err);
6449fa9c1c2SMaxim Levitsky     if (local_err) {
6459fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
6469fa9c1c2SMaxim Levitsky         return -1;
6479fa9c1c2SMaxim Levitsky     }
6489fa9c1c2SMaxim Levitsky 
6499fa9c1c2SMaxim Levitsky     luks->cipher_alg =
6509fa9c1c2SMaxim Levitsky             qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name,
6519fa9c1c2SMaxim Levitsky                                                   luks->cipher_mode,
6529fa9c1c2SMaxim Levitsky                                                   luks->header.master_key_len,
6539fa9c1c2SMaxim Levitsky                                                   &local_err);
6549fa9c1c2SMaxim Levitsky     if (local_err) {
6559fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
6569fa9c1c2SMaxim Levitsky         return -1;
6579fa9c1c2SMaxim Levitsky     }
6589fa9c1c2SMaxim Levitsky 
6599fa9c1c2SMaxim Levitsky     luks->hash_alg =
6609fa9c1c2SMaxim Levitsky             qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec,
6619fa9c1c2SMaxim Levitsky                                                 &local_err);
6629fa9c1c2SMaxim Levitsky     if (local_err) {
6639fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
6649fa9c1c2SMaxim Levitsky         return -1;
6659fa9c1c2SMaxim Levitsky     }
6669fa9c1c2SMaxim Levitsky 
6679fa9c1c2SMaxim Levitsky     luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name,
6689fa9c1c2SMaxim Levitsky                                                            &local_err);
6699fa9c1c2SMaxim Levitsky     if (local_err) {
6709fa9c1c2SMaxim Levitsky         error_propagate(errp, local_err);
6719fa9c1c2SMaxim Levitsky         return -1;
6729fa9c1c2SMaxim Levitsky     }
6739fa9c1c2SMaxim Levitsky 
6749fa9c1c2SMaxim Levitsky     if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
6759fa9c1c2SMaxim Levitsky         if (!ivhash_name) {
6769fa9c1c2SMaxim Levitsky             error_setg(errp, "Missing IV generator hash specification");
6779fa9c1c2SMaxim Levitsky             return -1;
6789fa9c1c2SMaxim Levitsky         }
6799fa9c1c2SMaxim Levitsky         luks->ivgen_cipher_alg =
6809fa9c1c2SMaxim Levitsky                 qcrypto_block_luks_essiv_cipher(luks->cipher_alg,
6819fa9c1c2SMaxim Levitsky                                                 luks->ivgen_hash_alg,
6829fa9c1c2SMaxim Levitsky                                                 &local_err);
6839fa9c1c2SMaxim Levitsky         if (local_err) {
6849fa9c1c2SMaxim Levitsky             error_propagate(errp, local_err);
6859fa9c1c2SMaxim Levitsky             return -1;
6869fa9c1c2SMaxim Levitsky         }
6879fa9c1c2SMaxim Levitsky     } else {
6889fa9c1c2SMaxim Levitsky 
6899fa9c1c2SMaxim Levitsky         /*
6909fa9c1c2SMaxim Levitsky          * Note we parsed the ivhash_name earlier in the cipher_mode
6919fa9c1c2SMaxim Levitsky          * spec string even with plain/plain64 ivgens, but we
6929fa9c1c2SMaxim Levitsky          * will ignore it, since it is irrelevant for these ivgens.
6939fa9c1c2SMaxim Levitsky          * This is for compat with dm-crypt which will silently
6949fa9c1c2SMaxim Levitsky          * ignore hash names with these ivgens rather than report
6959fa9c1c2SMaxim Levitsky          * an error about the invalid usage
6969fa9c1c2SMaxim Levitsky          */
6979fa9c1c2SMaxim Levitsky         luks->ivgen_cipher_alg = luks->cipher_alg;
6989fa9c1c2SMaxim Levitsky     }
6999fa9c1c2SMaxim Levitsky     return 0;
7009fa9c1c2SMaxim Levitsky }
7019fa9c1c2SMaxim Levitsky 
7029fa9c1c2SMaxim Levitsky /*
7033994a7c9SMaxim Levitsky  * Given a key slot,  user password, and the master key,
7043994a7c9SMaxim Levitsky  * will store the encrypted master key there, and update the
7053994a7c9SMaxim Levitsky  * in-memory header. User must then write the in-memory header
7063994a7c9SMaxim Levitsky  *
7073994a7c9SMaxim Levitsky  * Returns:
7083994a7c9SMaxim Levitsky  *    0 if the keyslot was written successfully
7093994a7c9SMaxim Levitsky  *      with the provided password
7103994a7c9SMaxim Levitsky  *   -1 if a fatal error occurred while storing the key
7113994a7c9SMaxim Levitsky  */
7123994a7c9SMaxim Levitsky static int
7133994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block,
7143994a7c9SMaxim Levitsky                              unsigned int slot_idx,
7153994a7c9SMaxim Levitsky                              const char *password,
7163994a7c9SMaxim Levitsky                              uint8_t *masterkey,
7173994a7c9SMaxim Levitsky                              uint64_t iter_time,
7183994a7c9SMaxim Levitsky                              QCryptoBlockWriteFunc writefunc,
7193994a7c9SMaxim Levitsky                              void *opaque,
7203994a7c9SMaxim Levitsky                              Error **errp)
7213994a7c9SMaxim Levitsky {
7223994a7c9SMaxim Levitsky     QCryptoBlockLUKS *luks = block->opaque;
7233994a7c9SMaxim Levitsky     QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx];
7243994a7c9SMaxim Levitsky     g_autofree uint8_t *splitkey = NULL;
7253994a7c9SMaxim Levitsky     size_t splitkeylen;
7263994a7c9SMaxim Levitsky     g_autofree uint8_t *slotkey = NULL;
7273994a7c9SMaxim Levitsky     g_autoptr(QCryptoCipher) cipher = NULL;
7283994a7c9SMaxim Levitsky     g_autoptr(QCryptoIVGen) ivgen = NULL;
7293994a7c9SMaxim Levitsky     Error *local_err = NULL;
7303994a7c9SMaxim Levitsky     uint64_t iters;
7313994a7c9SMaxim Levitsky     int ret = -1;
7323994a7c9SMaxim Levitsky 
7333994a7c9SMaxim Levitsky     if (qcrypto_random_bytes(slot->salt,
7343994a7c9SMaxim Levitsky                              QCRYPTO_BLOCK_LUKS_SALT_LEN,
7353994a7c9SMaxim Levitsky                              errp) < 0) {
7363994a7c9SMaxim Levitsky         goto cleanup;
7373994a7c9SMaxim Levitsky     }
7383994a7c9SMaxim Levitsky 
7393994a7c9SMaxim Levitsky     splitkeylen = luks->header.master_key_len * slot->stripes;
7403994a7c9SMaxim Levitsky 
7413994a7c9SMaxim Levitsky     /*
7423994a7c9SMaxim Levitsky      * Determine how many iterations are required to
7433994a7c9SMaxim Levitsky      * hash the user password while consuming 1 second of compute
7443994a7c9SMaxim Levitsky      * time
7453994a7c9SMaxim Levitsky      */
7463994a7c9SMaxim Levitsky     iters = qcrypto_pbkdf2_count_iters(luks->hash_alg,
7473994a7c9SMaxim Levitsky                                        (uint8_t *)password, strlen(password),
7483994a7c9SMaxim Levitsky                                        slot->salt,
7493994a7c9SMaxim Levitsky                                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
7503994a7c9SMaxim Levitsky                                        luks->header.master_key_len,
7513994a7c9SMaxim Levitsky                                        &local_err);
7523994a7c9SMaxim Levitsky     if (local_err) {
7533994a7c9SMaxim Levitsky         error_propagate(errp, local_err);
7543994a7c9SMaxim Levitsky         goto cleanup;
7553994a7c9SMaxim Levitsky     }
7563994a7c9SMaxim Levitsky 
7573994a7c9SMaxim Levitsky     if (iters > (ULLONG_MAX / iter_time)) {
7583994a7c9SMaxim Levitsky         error_setg_errno(errp, ERANGE,
7593994a7c9SMaxim Levitsky                          "PBKDF iterations %llu too large to scale",
7603994a7c9SMaxim Levitsky                          (unsigned long long)iters);
7613994a7c9SMaxim Levitsky         goto cleanup;
7623994a7c9SMaxim Levitsky     }
7633994a7c9SMaxim Levitsky 
7643994a7c9SMaxim Levitsky     /* iter_time was in millis, but count_iters reported for secs */
7653994a7c9SMaxim Levitsky     iters = iters * iter_time / 1000;
7663994a7c9SMaxim Levitsky 
7673994a7c9SMaxim Levitsky     if (iters > UINT32_MAX) {
7683994a7c9SMaxim Levitsky         error_setg_errno(errp, ERANGE,
7693994a7c9SMaxim Levitsky                          "PBKDF iterations %llu larger than %u",
7703994a7c9SMaxim Levitsky                          (unsigned long long)iters, UINT32_MAX);
7713994a7c9SMaxim Levitsky         goto cleanup;
7723994a7c9SMaxim Levitsky     }
7733994a7c9SMaxim Levitsky 
7743994a7c9SMaxim Levitsky     slot->iterations =
7753994a7c9SMaxim Levitsky         MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS);
7763994a7c9SMaxim Levitsky 
7773994a7c9SMaxim Levitsky 
7783994a7c9SMaxim Levitsky     /*
7793994a7c9SMaxim Levitsky      * Generate a key that we'll use to encrypt the master
7803994a7c9SMaxim Levitsky      * key, from the user's password
7813994a7c9SMaxim Levitsky      */
7823994a7c9SMaxim Levitsky     slotkey = g_new0(uint8_t, luks->header.master_key_len);
7833994a7c9SMaxim Levitsky     if (qcrypto_pbkdf2(luks->hash_alg,
7843994a7c9SMaxim Levitsky                        (uint8_t *)password, strlen(password),
7853994a7c9SMaxim Levitsky                        slot->salt,
7863994a7c9SMaxim Levitsky                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
7873994a7c9SMaxim Levitsky                        slot->iterations,
7883994a7c9SMaxim Levitsky                        slotkey, luks->header.master_key_len,
7893994a7c9SMaxim Levitsky                        errp) < 0) {
7903994a7c9SMaxim Levitsky         goto cleanup;
7913994a7c9SMaxim Levitsky     }
7923994a7c9SMaxim Levitsky 
7933994a7c9SMaxim Levitsky 
7943994a7c9SMaxim Levitsky     /*
7953994a7c9SMaxim Levitsky      * Setup the encryption objects needed to encrypt the
7963994a7c9SMaxim Levitsky      * master key material
7973994a7c9SMaxim Levitsky      */
7983994a7c9SMaxim Levitsky     cipher = qcrypto_cipher_new(luks->cipher_alg,
7993994a7c9SMaxim Levitsky                                 luks->cipher_mode,
8003994a7c9SMaxim Levitsky                                 slotkey, luks->header.master_key_len,
8013994a7c9SMaxim Levitsky                                 errp);
8023994a7c9SMaxim Levitsky     if (!cipher) {
8033994a7c9SMaxim Levitsky         goto cleanup;
8043994a7c9SMaxim Levitsky     }
8053994a7c9SMaxim Levitsky 
8063994a7c9SMaxim Levitsky     ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
8073994a7c9SMaxim Levitsky                               luks->ivgen_cipher_alg,
8083994a7c9SMaxim Levitsky                               luks->ivgen_hash_alg,
8093994a7c9SMaxim Levitsky                               slotkey, luks->header.master_key_len,
8103994a7c9SMaxim Levitsky                               errp);
8113994a7c9SMaxim Levitsky     if (!ivgen) {
8123994a7c9SMaxim Levitsky         goto cleanup;
8133994a7c9SMaxim Levitsky     }
8143994a7c9SMaxim Levitsky 
8153994a7c9SMaxim Levitsky     /*
8163994a7c9SMaxim Levitsky      * Before storing the master key, we need to vastly
8173994a7c9SMaxim Levitsky      * increase its size, as protection against forensic
8183994a7c9SMaxim Levitsky      * disk data recovery
8193994a7c9SMaxim Levitsky      */
8203994a7c9SMaxim Levitsky     splitkey = g_new0(uint8_t, splitkeylen);
8213994a7c9SMaxim Levitsky 
8223994a7c9SMaxim Levitsky     if (qcrypto_afsplit_encode(luks->hash_alg,
8233994a7c9SMaxim Levitsky                                luks->header.master_key_len,
8243994a7c9SMaxim Levitsky                                slot->stripes,
8253994a7c9SMaxim Levitsky                                masterkey,
8263994a7c9SMaxim Levitsky                                splitkey,
8273994a7c9SMaxim Levitsky                                errp) < 0) {
8283994a7c9SMaxim Levitsky         goto cleanup;
8293994a7c9SMaxim Levitsky     }
8303994a7c9SMaxim Levitsky 
8313994a7c9SMaxim Levitsky     /*
8323994a7c9SMaxim Levitsky      * Now we encrypt the split master key with the key generated
8333994a7c9SMaxim Levitsky      * from the user's password, before storing it
8343994a7c9SMaxim Levitsky      */
8353994a7c9SMaxim Levitsky     if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
8363994a7c9SMaxim Levitsky                                             QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
8373994a7c9SMaxim Levitsky                                             0,
8383994a7c9SMaxim Levitsky                                             splitkey,
8393994a7c9SMaxim Levitsky                                             splitkeylen,
8403994a7c9SMaxim Levitsky                                             errp) < 0) {
8413994a7c9SMaxim Levitsky         goto cleanup;
8423994a7c9SMaxim Levitsky     }
8433994a7c9SMaxim Levitsky 
8443994a7c9SMaxim Levitsky     /* Write out the slot's master key material. */
8453994a7c9SMaxim Levitsky     if (writefunc(block,
8463994a7c9SMaxim Levitsky                   slot->key_offset_sector *
8473994a7c9SMaxim Levitsky                   QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
8483994a7c9SMaxim Levitsky                   splitkey, splitkeylen,
8493994a7c9SMaxim Levitsky                   opaque,
8503994a7c9SMaxim Levitsky                   errp) != splitkeylen) {
8513994a7c9SMaxim Levitsky         goto cleanup;
8523994a7c9SMaxim Levitsky     }
8533994a7c9SMaxim Levitsky 
8543994a7c9SMaxim Levitsky     slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
8553994a7c9SMaxim Levitsky 
8563994a7c9SMaxim Levitsky     if (qcrypto_block_luks_store_header(block,  writefunc, opaque, errp) < 0) {
8573994a7c9SMaxim Levitsky         goto cleanup;
8583994a7c9SMaxim Levitsky     }
8593994a7c9SMaxim Levitsky 
8603994a7c9SMaxim Levitsky     ret = 0;
8613994a7c9SMaxim Levitsky 
8623994a7c9SMaxim Levitsky cleanup:
8633994a7c9SMaxim Levitsky     if (slotkey) {
8643994a7c9SMaxim Levitsky         memset(slotkey, 0, luks->header.master_key_len);
8653994a7c9SMaxim Levitsky     }
8663994a7c9SMaxim Levitsky     if (splitkey) {
8673994a7c9SMaxim Levitsky         memset(splitkey, 0, splitkeylen);
8683994a7c9SMaxim Levitsky     }
8693994a7c9SMaxim Levitsky     return ret;
8703994a7c9SMaxim Levitsky }
8713994a7c9SMaxim Levitsky 
8723994a7c9SMaxim Levitsky /*
8733e308f20SDaniel P. Berrange  * Given a key slot, and user password, this will attempt to unlock
8743e308f20SDaniel P. Berrange  * the master encryption key from the key slot.
8753e308f20SDaniel P. Berrange  *
8763e308f20SDaniel P. Berrange  * Returns:
8773e308f20SDaniel P. Berrange  *    0 if the key slot is disabled, or key could not be decrypted
8783e308f20SDaniel P. Berrange  *      with the provided password
8793e308f20SDaniel P. Berrange  *    1 if the key slot is enabled, and key decrypted successfully
8803e308f20SDaniel P. Berrange  *      with the provided password
8813e308f20SDaniel P. Berrange  *   -1 if a fatal error occurred loading the key
8823e308f20SDaniel P. Berrange  */
8833e308f20SDaniel P. Berrange static int
8843e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block,
8857e60a6f5SMaxim Levitsky                             size_t slot_idx,
8863e308f20SDaniel P. Berrange                             const char *password,
8873e308f20SDaniel P. Berrange                             uint8_t *masterkey,
8883e308f20SDaniel P. Berrange                             QCryptoBlockReadFunc readfunc,
8893e308f20SDaniel P. Berrange                             void *opaque,
8903e308f20SDaniel P. Berrange                             Error **errp)
8913e308f20SDaniel P. Berrange {
8923e308f20SDaniel P. Berrange     QCryptoBlockLUKS *luks = block->opaque;
8937e60a6f5SMaxim Levitsky     const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx];
89457b9f113SDaniel P. Berrangé     g_autofree uint8_t *splitkey = NULL;
8953e308f20SDaniel P. Berrange     size_t splitkeylen;
89657b9f113SDaniel P. Berrangé     g_autofree uint8_t *possiblekey = NULL;
8973e308f20SDaniel P. Berrange     ssize_t rv;
89857b9f113SDaniel P. Berrangé     g_autoptr(QCryptoCipher) cipher = NULL;
8993e308f20SDaniel P. Berrange     uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
90057b9f113SDaniel P. Berrangé     g_autoptr(QCryptoIVGen) ivgen = NULL;
9013e308f20SDaniel P. Berrange     size_t niv;
9023e308f20SDaniel P. Berrange 
9033e308f20SDaniel P. Berrange     if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
9043e308f20SDaniel P. Berrange         return 0;
9053e308f20SDaniel P. Berrange     }
9063e308f20SDaniel P. Berrange 
9071ddd52e4SMaxim Levitsky     splitkeylen = luks->header.master_key_len * slot->stripes;
9083e308f20SDaniel P. Berrange     splitkey = g_new0(uint8_t, splitkeylen);
9091ddd52e4SMaxim Levitsky     possiblekey = g_new0(uint8_t, luks->header.master_key_len);
9103e308f20SDaniel P. Berrange 
9113e308f20SDaniel P. Berrange     /*
9123e308f20SDaniel P. Berrange      * The user password is used to generate a (possible)
9133e308f20SDaniel P. Berrange      * decryption key. This may or may not successfully
9143e308f20SDaniel P. Berrange      * decrypt the master key - we just blindly assume
9153e308f20SDaniel P. Berrange      * the key is correct and validate the results of
9163e308f20SDaniel P. Berrange      * decryption later.
9173e308f20SDaniel P. Berrange      */
9189d80e59dSMaxim Levitsky     if (qcrypto_pbkdf2(luks->hash_alg,
9193e308f20SDaniel P. Berrange                        (const uint8_t *)password, strlen(password),
9203e308f20SDaniel P. Berrange                        slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN,
9213e308f20SDaniel P. Berrange                        slot->iterations,
9221ddd52e4SMaxim Levitsky                        possiblekey, luks->header.master_key_len,
9233e308f20SDaniel P. Berrange                        errp) < 0) {
92457b9f113SDaniel P. Berrangé         return -1;
9253e308f20SDaniel P. Berrange     }
9263e308f20SDaniel P. Berrange 
9273e308f20SDaniel P. Berrange     /*
9283e308f20SDaniel P. Berrange      * We need to read the master key material from the
9293e308f20SDaniel P. Berrange      * LUKS key material header. What we're reading is
9303e308f20SDaniel P. Berrange      * not the raw master key, but rather the data after
9313e308f20SDaniel P. Berrange      * it has been passed through AFSplit and the result
9323e308f20SDaniel P. Berrange      * then encrypted.
9333e308f20SDaniel P. Berrange      */
9343e308f20SDaniel P. Berrange     rv = readfunc(block,
935f0d3c362SMaxim Levitsky                   slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
9363e308f20SDaniel P. Berrange                   splitkey, splitkeylen,
937e4a3507eSDaniel P. Berrange                   opaque,
93837509233SFam Zheng                   errp);
9393e308f20SDaniel P. Berrange     if (rv < 0) {
94057b9f113SDaniel P. Berrangé         return -1;
9413e308f20SDaniel P. Berrange     }
9423e308f20SDaniel P. Berrange 
9433e308f20SDaniel P. Berrange 
9443e308f20SDaniel P. Berrange     /* Setup the cipher/ivgen that we'll use to try to decrypt
9453e308f20SDaniel P. Berrange      * the split master key material */
9469d80e59dSMaxim Levitsky     cipher = qcrypto_cipher_new(luks->cipher_alg,
9479d80e59dSMaxim Levitsky                                 luks->cipher_mode,
9489d80e59dSMaxim Levitsky                                 possiblekey,
9499d80e59dSMaxim Levitsky                                 luks->header.master_key_len,
9503e308f20SDaniel P. Berrange                                 errp);
9513e308f20SDaniel P. Berrange     if (!cipher) {
95257b9f113SDaniel P. Berrangé         return -1;
9533e308f20SDaniel P. Berrange     }
9543e308f20SDaniel P. Berrange 
9559d80e59dSMaxim Levitsky     niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
9569d80e59dSMaxim Levitsky                                     luks->cipher_mode);
9579d80e59dSMaxim Levitsky 
9589d80e59dSMaxim Levitsky     ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
9599d80e59dSMaxim Levitsky                               luks->ivgen_cipher_alg,
9609d80e59dSMaxim Levitsky                               luks->ivgen_hash_alg,
9619d80e59dSMaxim Levitsky                               possiblekey,
9629d80e59dSMaxim Levitsky                               luks->header.master_key_len,
9633e308f20SDaniel P. Berrange                               errp);
9643e308f20SDaniel P. Berrange     if (!ivgen) {
96557b9f113SDaniel P. Berrangé         return -1;
9663e308f20SDaniel P. Berrange     }
9673e308f20SDaniel P. Berrange 
9683e308f20SDaniel P. Berrange 
9693e308f20SDaniel P. Berrange     /*
9703e308f20SDaniel P. Berrange      * The master key needs to be decrypted in the same
9713e308f20SDaniel P. Berrange      * way that the block device payload will be decrypted
9723e308f20SDaniel P. Berrange      * later. In particular we'll be using the IV generator
9733e308f20SDaniel P. Berrange      * to reset the encryption cipher every time the master
9743e308f20SDaniel P. Berrange      * key crosses a sector boundary.
9753e308f20SDaniel P. Berrange      */
9760270417cSVladimir Sementsov-Ogievskiy     if (qcrypto_block_cipher_decrypt_helper(cipher,
9773e308f20SDaniel P. Berrange                                             niv,
9783e308f20SDaniel P. Berrange                                             ivgen,
9793e308f20SDaniel P. Berrange                                             QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
9803e308f20SDaniel P. Berrange                                             0,
9813e308f20SDaniel P. Berrange                                             splitkey,
9823e308f20SDaniel P. Berrange                                             splitkeylen,
9833e308f20SDaniel P. Berrange                                             errp) < 0) {
98457b9f113SDaniel P. Berrangé         return -1;
9853e308f20SDaniel P. Berrange     }
9863e308f20SDaniel P. Berrange 
9873e308f20SDaniel P. Berrange     /*
9883e308f20SDaniel P. Berrange      * Now we've decrypted the split master key, join
9893e308f20SDaniel P. Berrange      * it back together to get the actual master key.
9903e308f20SDaniel P. Berrange      */
9919d80e59dSMaxim Levitsky     if (qcrypto_afsplit_decode(luks->hash_alg,
9921ddd52e4SMaxim Levitsky                                luks->header.master_key_len,
9933e308f20SDaniel P. Berrange                                slot->stripes,
9943e308f20SDaniel P. Berrange                                splitkey,
9953e308f20SDaniel P. Berrange                                masterkey,
9963e308f20SDaniel P. Berrange                                errp) < 0) {
99757b9f113SDaniel P. Berrangé         return -1;
9983e308f20SDaniel P. Berrange     }
9993e308f20SDaniel P. Berrange 
10003e308f20SDaniel P. Berrange 
10013e308f20SDaniel P. Berrange     /*
10023e308f20SDaniel P. Berrange      * We still don't know that the masterkey we got is valid,
10033e308f20SDaniel P. Berrange      * because we just blindly assumed the user's password
10043e308f20SDaniel P. Berrange      * was correct. This is where we now verify it. We are
10053e308f20SDaniel P. Berrange      * creating a hash of the master key using PBKDF and
10063e308f20SDaniel P. Berrange      * then comparing that to the hash stored in the key slot
10073e308f20SDaniel P. Berrange      * header
10083e308f20SDaniel P. Berrange      */
10099d80e59dSMaxim Levitsky     if (qcrypto_pbkdf2(luks->hash_alg,
10101ddd52e4SMaxim Levitsky                        masterkey,
10111ddd52e4SMaxim Levitsky                        luks->header.master_key_len,
10123e308f20SDaniel P. Berrange                        luks->header.master_key_salt,
10133e308f20SDaniel P. Berrange                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
10143e308f20SDaniel P. Berrange                        luks->header.master_key_iterations,
10151ddd52e4SMaxim Levitsky                        keydigest,
10161ddd52e4SMaxim Levitsky                        G_N_ELEMENTS(keydigest),
10173e308f20SDaniel P. Berrange                        errp) < 0) {
101857b9f113SDaniel P. Berrangé         return -1;
10193e308f20SDaniel P. Berrange     }
10203e308f20SDaniel P. Berrange 
10213e308f20SDaniel P. Berrange     if (memcmp(keydigest, luks->header.master_key_digest,
10223e308f20SDaniel P. Berrange                QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) {
10233e308f20SDaniel P. Berrange         /* Success, we got the right master key */
102457b9f113SDaniel P. Berrangé         return 1;
10253e308f20SDaniel P. Berrange     }
10263e308f20SDaniel P. Berrange 
10273e308f20SDaniel P. Berrange     /* Fail, user's password was not valid for this key slot,
10283e308f20SDaniel P. Berrange      * tell caller to try another slot */
102957b9f113SDaniel P. Berrangé     return 0;
10303e308f20SDaniel P. Berrange }
10313e308f20SDaniel P. Berrange 
10323e308f20SDaniel P. Berrange 
10333e308f20SDaniel P. Berrange /*
10343e308f20SDaniel P. Berrange  * Given a user password, this will iterate over all key
10353e308f20SDaniel P. Berrange  * slots and try to unlock each active key slot using the
10363e308f20SDaniel P. Berrange  * password until it successfully obtains a master key.
10373e308f20SDaniel P. Berrange  *
10383e308f20SDaniel P. Berrange  * Returns 0 if a key was loaded, -1 if no keys could be loaded
10393e308f20SDaniel P. Berrange  */
10403e308f20SDaniel P. Berrange static int
10413e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block,
10423e308f20SDaniel P. Berrange                             const char *password,
10431ddd52e4SMaxim Levitsky                             uint8_t *masterkey,
10443e308f20SDaniel P. Berrange                             QCryptoBlockReadFunc readfunc,
10453e308f20SDaniel P. Berrange                             void *opaque,
10463e308f20SDaniel P. Berrange                             Error **errp)
10473e308f20SDaniel P. Berrange {
10483e308f20SDaniel P. Berrange     size_t i;
10493e308f20SDaniel P. Berrange     int rv;
10503e308f20SDaniel P. Berrange 
10513e308f20SDaniel P. Berrange     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
10523e308f20SDaniel P. Berrange         rv = qcrypto_block_luks_load_key(block,
10537e60a6f5SMaxim Levitsky                                          i,
10543e308f20SDaniel P. Berrange                                          password,
10551ddd52e4SMaxim Levitsky                                          masterkey,
10563e308f20SDaniel P. Berrange                                          readfunc,
10573e308f20SDaniel P. Berrange                                          opaque,
10583e308f20SDaniel P. Berrange                                          errp);
10593e308f20SDaniel P. Berrange         if (rv < 0) {
10603e308f20SDaniel P. Berrange             goto error;
10613e308f20SDaniel P. Berrange         }
10623e308f20SDaniel P. Berrange         if (rv == 1) {
10633e308f20SDaniel P. Berrange             return 0;
10643e308f20SDaniel P. Berrange         }
10653e308f20SDaniel P. Berrange     }
10663e308f20SDaniel P. Berrange 
10673e308f20SDaniel P. Berrange     error_setg(errp, "Invalid password, cannot unlock any keyslot");
10683e308f20SDaniel P. Berrange  error:
10693e308f20SDaniel P. Berrange     return -1;
10703e308f20SDaniel P. Berrange }
10713e308f20SDaniel P. Berrange 
10723e308f20SDaniel P. Berrange 
10733e308f20SDaniel P. Berrange static int
10743e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block,
10753e308f20SDaniel P. Berrange                         QCryptoBlockOpenOptions *options,
10761cd9a787SDaniel P. Berrange                         const char *optprefix,
10773e308f20SDaniel P. Berrange                         QCryptoBlockReadFunc readfunc,
10783e308f20SDaniel P. Berrange                         void *opaque,
10793e308f20SDaniel P. Berrange                         unsigned int flags,
1080c972fa12SVladimir Sementsov-Ogievskiy                         size_t n_threads,
10813e308f20SDaniel P. Berrange                         Error **errp)
10823e308f20SDaniel P. Berrange {
10839d80e59dSMaxim Levitsky     QCryptoBlockLUKS *luks = NULL;
108457b9f113SDaniel P. Berrangé     g_autofree uint8_t *masterkey = NULL;
108557b9f113SDaniel P. Berrangé     g_autofree char *password = NULL;
10863e308f20SDaniel P. Berrange 
10873e308f20SDaniel P. Berrange     if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
10883e308f20SDaniel P. Berrange         if (!options->u.luks.key_secret) {
10891cd9a787SDaniel P. Berrange             error_setg(errp, "Parameter '%skey-secret' is required for cipher",
10901cd9a787SDaniel P. Berrange                        optprefix ? optprefix : "");
10913e308f20SDaniel P. Berrange             return -1;
10923e308f20SDaniel P. Berrange         }
10933e308f20SDaniel P. Berrange         password = qcrypto_secret_lookup_as_utf8(
10943e308f20SDaniel P. Berrange             options->u.luks.key_secret, errp);
10953e308f20SDaniel P. Berrange         if (!password) {
10963e308f20SDaniel P. Berrange             return -1;
10973e308f20SDaniel P. Berrange         }
10983e308f20SDaniel P. Berrange     }
10993e308f20SDaniel P. Berrange 
11003e308f20SDaniel P. Berrange     luks = g_new0(QCryptoBlockLUKS, 1);
11013e308f20SDaniel P. Berrange     block->opaque = luks;
11023e308f20SDaniel P. Berrange 
1103dde2c5afSMaxim Levitsky     if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) {
11043e308f20SDaniel P. Berrange         goto fail;
11053e308f20SDaniel P. Berrange     }
11063e308f20SDaniel P. Berrange 
11079fa9c1c2SMaxim Levitsky     if (qcrypto_block_luks_check_header(luks, errp) < 0) {
11083e308f20SDaniel P. Berrange         goto fail;
11093e308f20SDaniel P. Berrange     }
11103e308f20SDaniel P. Berrange 
11119fa9c1c2SMaxim Levitsky     if (qcrypto_block_luks_parse_header(luks, errp) < 0) {
11123e308f20SDaniel P. Berrange         goto fail;
11133e308f20SDaniel P. Berrange     }
11143e308f20SDaniel P. Berrange 
11153e308f20SDaniel P. Berrange     if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
11163e308f20SDaniel P. Berrange         /* Try to find which key slot our password is valid for
11173e308f20SDaniel P. Berrange          * and unlock the master key from that slot.
11183e308f20SDaniel P. Berrange          */
11191ddd52e4SMaxim Levitsky 
11201ddd52e4SMaxim Levitsky         masterkey = g_new0(uint8_t, luks->header.master_key_len);
11211ddd52e4SMaxim Levitsky 
11223e308f20SDaniel P. Berrange         if (qcrypto_block_luks_find_key(block,
11233e308f20SDaniel P. Berrange                                         password,
11241ddd52e4SMaxim Levitsky                                         masterkey,
11253e308f20SDaniel P. Berrange                                         readfunc, opaque,
11263e308f20SDaniel P. Berrange                                         errp) < 0) {
11273e308f20SDaniel P. Berrange             goto fail;
11283e308f20SDaniel P. Berrange         }
11293e308f20SDaniel P. Berrange 
11303e308f20SDaniel P. Berrange         /* We have a valid master key now, so can setup the
11313e308f20SDaniel P. Berrange          * block device payload decryption objects
11323e308f20SDaniel P. Berrange          */
11339d80e59dSMaxim Levitsky         block->kdfhash = luks->hash_alg;
11349d80e59dSMaxim Levitsky         block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
11359d80e59dSMaxim Levitsky                                                luks->cipher_mode);
11369d80e59dSMaxim Levitsky 
11379d80e59dSMaxim Levitsky         block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
11389d80e59dSMaxim Levitsky                                          luks->ivgen_cipher_alg,
11399d80e59dSMaxim Levitsky                                          luks->ivgen_hash_alg,
11401ddd52e4SMaxim Levitsky                                          masterkey,
11411ddd52e4SMaxim Levitsky                                          luks->header.master_key_len,
11423e308f20SDaniel P. Berrange                                          errp);
11433e308f20SDaniel P. Berrange         if (!block->ivgen) {
11443e308f20SDaniel P. Berrange             goto fail;
11453e308f20SDaniel P. Berrange         }
11463e308f20SDaniel P. Berrange 
114761dd8a9aSMaxim Levitsky         if (qcrypto_block_init_cipher(block,
11489d80e59dSMaxim Levitsky                                       luks->cipher_alg,
11499d80e59dSMaxim Levitsky                                       luks->cipher_mode,
11501ddd52e4SMaxim Levitsky                                       masterkey,
11511ddd52e4SMaxim Levitsky                                       luks->header.master_key_len,
11521ddd52e4SMaxim Levitsky                                       n_threads,
115361dd8a9aSMaxim Levitsky                                       errp) < 0) {
11543e308f20SDaniel P. Berrange             goto fail;
11553e308f20SDaniel P. Berrange         }
11563e308f20SDaniel P. Berrange     }
11573e308f20SDaniel P. Berrange 
1158850f49deSDaniel P. Berrange     block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
1159f0d3c362SMaxim Levitsky     block->payload_offset = luks->header.payload_offset_sector *
1160850f49deSDaniel P. Berrange         block->sector_size;
11613e308f20SDaniel P. Berrange 
11623e308f20SDaniel P. Berrange     return 0;
11633e308f20SDaniel P. Berrange 
11643e308f20SDaniel P. Berrange  fail:
1165c972fa12SVladimir Sementsov-Ogievskiy     qcrypto_block_free_cipher(block);
11663e308f20SDaniel P. Berrange     qcrypto_ivgen_free(block->ivgen);
11673e308f20SDaniel P. Berrange     g_free(luks);
116861dd8a9aSMaxim Levitsky     return -1;
11693e308f20SDaniel P. Berrange }
11703e308f20SDaniel P. Berrange 
11713e308f20SDaniel P. Berrange 
11722ef950f9SFam Zheng static void
11732ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
11743e308f20SDaniel P. Berrange {
11752ef950f9SFam Zheng     QemuUUID uuid;
11762ef950f9SFam Zheng     qemu_uuid_generate(&uuid);
11772ef950f9SFam Zheng     qemu_uuid_unparse(&uuid, (char *)uuidstr);
11783e308f20SDaniel P. Berrange }
11793e308f20SDaniel P. Berrange 
11803e308f20SDaniel P. Berrange static int
11813e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block,
11823e308f20SDaniel P. Berrange                           QCryptoBlockCreateOptions *options,
11831cd9a787SDaniel P. Berrange                           const char *optprefix,
11843e308f20SDaniel P. Berrange                           QCryptoBlockInitFunc initfunc,
11853e308f20SDaniel P. Berrange                           QCryptoBlockWriteFunc writefunc,
11863e308f20SDaniel P. Berrange                           void *opaque,
11873e308f20SDaniel P. Berrange                           Error **errp)
11883e308f20SDaniel P. Berrange {
11893e308f20SDaniel P. Berrange     QCryptoBlockLUKS *luks;
11903e308f20SDaniel P. Berrange     QCryptoBlockCreateOptionsLUKS luks_opts;
11913e308f20SDaniel P. Berrange     Error *local_err = NULL;
119257b9f113SDaniel P. Berrangé     g_autofree uint8_t *masterkey = NULL;
1193bd56a55aSMaxim Levitsky     size_t header_sectors;
1194bd56a55aSMaxim Levitsky     size_t split_key_sectors;
11953e308f20SDaniel P. Berrange     size_t i;
119657b9f113SDaniel P. Berrangé     g_autofree char *password = NULL;
11973e308f20SDaniel P. Berrange     const char *cipher_alg;
11983e308f20SDaniel P. Berrange     const char *cipher_mode;
11993e308f20SDaniel P. Berrange     const char *ivgen_alg;
12003e308f20SDaniel P. Berrange     const char *ivgen_hash_alg = NULL;
12013e308f20SDaniel P. Berrange     const char *hash_alg;
120257b9f113SDaniel P. Berrangé     g_autofree char *cipher_mode_spec = NULL;
120359b060beSDaniel P. Berrange     uint64_t iters;
12043e308f20SDaniel P. Berrange 
12053e308f20SDaniel P. Berrange     memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
12063bd18890SDaniel P. Berrange     if (!luks_opts.has_iter_time) {
12072ab66cd5SDaniel P. Berrange         luks_opts.iter_time = 2000;
12083bd18890SDaniel P. Berrange     }
12093e308f20SDaniel P. Berrange     if (!luks_opts.has_cipher_alg) {
12103e308f20SDaniel P. Berrange         luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
12113e308f20SDaniel P. Berrange     }
12123e308f20SDaniel P. Berrange     if (!luks_opts.has_cipher_mode) {
12133e308f20SDaniel P. Berrange         luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS;
12143e308f20SDaniel P. Berrange     }
12153e308f20SDaniel P. Berrange     if (!luks_opts.has_ivgen_alg) {
12163e308f20SDaniel P. Berrange         luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64;
12173e308f20SDaniel P. Berrange     }
12183e308f20SDaniel P. Berrange     if (!luks_opts.has_hash_alg) {
12193e308f20SDaniel P. Berrange         luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256;
12203e308f20SDaniel P. Berrange     }
12218b7cdba3SDaniel P. Berrange     if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
12228b7cdba3SDaniel P. Berrange         if (!luks_opts.has_ivgen_hash_alg) {
12238b7cdba3SDaniel P. Berrange             luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256;
12248b7cdba3SDaniel P. Berrange             luks_opts.has_ivgen_hash_alg = true;
12258b7cdba3SDaniel P. Berrange         }
12268b7cdba3SDaniel P. Berrange     }
12279d80e59dSMaxim Levitsky 
12289d80e59dSMaxim Levitsky     luks = g_new0(QCryptoBlockLUKS, 1);
12299d80e59dSMaxim Levitsky     block->opaque = luks;
12309d80e59dSMaxim Levitsky 
12319d80e59dSMaxim Levitsky     luks->cipher_alg = luks_opts.cipher_alg;
12329d80e59dSMaxim Levitsky     luks->cipher_mode = luks_opts.cipher_mode;
12339d80e59dSMaxim Levitsky     luks->ivgen_alg = luks_opts.ivgen_alg;
12349d80e59dSMaxim Levitsky     luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
12359d80e59dSMaxim Levitsky     luks->hash_alg = luks_opts.hash_alg;
12369d80e59dSMaxim Levitsky 
12379d80e59dSMaxim Levitsky 
12388b7cdba3SDaniel P. Berrange     /* Note we're allowing ivgen_hash_alg to be set even for
12398b7cdba3SDaniel P. Berrange      * non-essiv iv generators that don't need a hash. It will
12408b7cdba3SDaniel P. Berrange      * be silently ignored, for compatibility with dm-crypt */
12413e308f20SDaniel P. Berrange 
12423e308f20SDaniel P. Berrange     if (!options->u.luks.key_secret) {
12431cd9a787SDaniel P. Berrange         error_setg(errp, "Parameter '%skey-secret' is required for cipher",
12441cd9a787SDaniel P. Berrange                    optprefix ? optprefix : "");
12459d80e59dSMaxim Levitsky         goto error;
12463e308f20SDaniel P. Berrange     }
12473e308f20SDaniel P. Berrange     password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
12483e308f20SDaniel P. Berrange     if (!password) {
12499d80e59dSMaxim Levitsky         goto error;
12503e308f20SDaniel P. Berrange     }
12513e308f20SDaniel P. Berrange 
12523e308f20SDaniel P. Berrange 
12533e308f20SDaniel P. Berrange     memcpy(luks->header.magic, qcrypto_block_luks_magic,
12543e308f20SDaniel P. Berrange            QCRYPTO_BLOCK_LUKS_MAGIC_LEN);
12553e308f20SDaniel P. Berrange 
12563e308f20SDaniel P. Berrange     /* We populate the header in native endianness initially and
12573e308f20SDaniel P. Berrange      * then convert everything to big endian just before writing
12583e308f20SDaniel P. Berrange      * it out to disk
12593e308f20SDaniel P. Berrange      */
12603e308f20SDaniel P. Berrange     luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION;
12612ef950f9SFam Zheng     qcrypto_block_luks_uuid_gen(luks->header.uuid);
12623e308f20SDaniel P. Berrange 
12633e308f20SDaniel P. Berrange     cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg,
12643e308f20SDaniel P. Berrange                                                       errp);
12653e308f20SDaniel P. Berrange     if (!cipher_alg) {
12663e308f20SDaniel P. Berrange         goto error;
12673e308f20SDaniel P. Berrange     }
12683e308f20SDaniel P. Berrange 
1269977c736fSMarkus Armbruster     cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode);
1270977c736fSMarkus Armbruster     ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg);
12713e308f20SDaniel P. Berrange     if (luks_opts.has_ivgen_hash_alg) {
1272977c736fSMarkus Armbruster         ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg);
12733e308f20SDaniel P. Berrange         cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
12743e308f20SDaniel P. Berrange                                            ivgen_hash_alg);
12753e308f20SDaniel P. Berrange     } else {
12763e308f20SDaniel P. Berrange         cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
12773e308f20SDaniel P. Berrange     }
1278977c736fSMarkus Armbruster     hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg);
12793e308f20SDaniel P. Berrange 
12803e308f20SDaniel P. Berrange 
12813e308f20SDaniel P. Berrange     if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
12823e308f20SDaniel P. Berrange         error_setg(errp, "Cipher name '%s' is too long for LUKS header",
12833e308f20SDaniel P. Berrange                    cipher_alg);
12843e308f20SDaniel P. Berrange         goto error;
12853e308f20SDaniel P. Berrange     }
12863e308f20SDaniel P. Berrange     if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) {
12873e308f20SDaniel P. Berrange         error_setg(errp, "Cipher mode '%s' is too long for LUKS header",
12883e308f20SDaniel P. Berrange                    cipher_mode_spec);
12893e308f20SDaniel P. Berrange         goto error;
12903e308f20SDaniel P. Berrange     }
12913e308f20SDaniel P. Berrange     if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) {
12923e308f20SDaniel P. Berrange         error_setg(errp, "Hash name '%s' is too long for LUKS header",
12933e308f20SDaniel P. Berrange                    hash_alg);
12943e308f20SDaniel P. Berrange         goto error;
12953e308f20SDaniel P. Berrange     }
12963e308f20SDaniel P. Berrange 
12973e308f20SDaniel P. Berrange     if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
12989d80e59dSMaxim Levitsky         luks->ivgen_cipher_alg =
12999d80e59dSMaxim Levitsky                 qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg,
13003e308f20SDaniel P. Berrange                                                 luks_opts.ivgen_hash_alg,
13013e308f20SDaniel P. Berrange                                                 &local_err);
13023e308f20SDaniel P. Berrange         if (local_err) {
13033e308f20SDaniel P. Berrange             error_propagate(errp, local_err);
13043e308f20SDaniel P. Berrange             goto error;
13053e308f20SDaniel P. Berrange         }
13063e308f20SDaniel P. Berrange     } else {
13079d80e59dSMaxim Levitsky         luks->ivgen_cipher_alg = luks_opts.cipher_alg;
13083e308f20SDaniel P. Berrange     }
13093e308f20SDaniel P. Berrange 
13103e308f20SDaniel P. Berrange     strcpy(luks->header.cipher_name, cipher_alg);
13113e308f20SDaniel P. Berrange     strcpy(luks->header.cipher_mode, cipher_mode_spec);
13123e308f20SDaniel P. Berrange     strcpy(luks->header.hash_spec, hash_alg);
13133e308f20SDaniel P. Berrange 
1314f0d3c362SMaxim Levitsky     luks->header.master_key_len =
1315f0d3c362SMaxim Levitsky         qcrypto_cipher_get_key_len(luks_opts.cipher_alg);
1316f0d3c362SMaxim Levitsky 
13173e308f20SDaniel P. Berrange     if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) {
1318f0d3c362SMaxim Levitsky         luks->header.master_key_len *= 2;
13193e308f20SDaniel P. Berrange     }
13203e308f20SDaniel P. Berrange 
13213e308f20SDaniel P. Berrange     /* Generate the salt used for hashing the master key
13223e308f20SDaniel P. Berrange      * with PBKDF later
13233e308f20SDaniel P. Berrange      */
13243e308f20SDaniel P. Berrange     if (qcrypto_random_bytes(luks->header.master_key_salt,
13253e308f20SDaniel P. Berrange                              QCRYPTO_BLOCK_LUKS_SALT_LEN,
13263e308f20SDaniel P. Berrange                              errp) < 0) {
13273e308f20SDaniel P. Berrange         goto error;
13283e308f20SDaniel P. Berrange     }
13293e308f20SDaniel P. Berrange 
13303e308f20SDaniel P. Berrange     /* Generate random master key */
1331f0d3c362SMaxim Levitsky     masterkey = g_new0(uint8_t, luks->header.master_key_len);
13323e308f20SDaniel P. Berrange     if (qcrypto_random_bytes(masterkey,
1333f0d3c362SMaxim Levitsky                              luks->header.master_key_len, errp) < 0) {
13343e308f20SDaniel P. Berrange         goto error;
13353e308f20SDaniel P. Berrange     }
13363e308f20SDaniel P. Berrange 
13373e308f20SDaniel P. Berrange 
13383e308f20SDaniel P. Berrange     /* Setup the block device payload encryption objects */
1339c972fa12SVladimir Sementsov-Ogievskiy     if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
1340c972fa12SVladimir Sementsov-Ogievskiy                                   luks_opts.cipher_mode, masterkey,
1341f0d3c362SMaxim Levitsky                                   luks->header.master_key_len, 1, errp) < 0) {
13423e308f20SDaniel P. Berrange         goto error;
13433e308f20SDaniel P. Berrange     }
13443e308f20SDaniel P. Berrange 
13453e308f20SDaniel P. Berrange     block->kdfhash = luks_opts.hash_alg;
13463e308f20SDaniel P. Berrange     block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg,
13473e308f20SDaniel P. Berrange                                            luks_opts.cipher_mode);
13483e308f20SDaniel P. Berrange     block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg,
13499d80e59dSMaxim Levitsky                                      luks->ivgen_cipher_alg,
13503e308f20SDaniel P. Berrange                                      luks_opts.ivgen_hash_alg,
1351f0d3c362SMaxim Levitsky                                      masterkey, luks->header.master_key_len,
13523e308f20SDaniel P. Berrange                                      errp);
13533e308f20SDaniel P. Berrange 
13543e308f20SDaniel P. Berrange     if (!block->ivgen) {
13553e308f20SDaniel P. Berrange         goto error;
13563e308f20SDaniel P. Berrange     }
13573e308f20SDaniel P. Berrange 
13583e308f20SDaniel P. Berrange 
13593e308f20SDaniel P. Berrange     /* Determine how many iterations we need to hash the master
13603e308f20SDaniel P. Berrange      * key, in order to have 1 second of compute time used
13613e308f20SDaniel P. Berrange      */
136259b060beSDaniel P. Berrange     iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
1363f0d3c362SMaxim Levitsky                                        masterkey, luks->header.master_key_len,
13643e308f20SDaniel P. Berrange                                        luks->header.master_key_salt,
13653e308f20SDaniel P. Berrange                                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
1366e74aabcfSDaniel P. Berrange                                        QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
13673e308f20SDaniel P. Berrange                                        &local_err);
13683e308f20SDaniel P. Berrange     if (local_err) {
13693e308f20SDaniel P. Berrange         error_propagate(errp, local_err);
13703e308f20SDaniel P. Berrange         goto error;
13713e308f20SDaniel P. Berrange     }
13723e308f20SDaniel P. Berrange 
13733bd18890SDaniel P. Berrange     if (iters > (ULLONG_MAX / luks_opts.iter_time)) {
13743bd18890SDaniel P. Berrange         error_setg_errno(errp, ERANGE,
13753bd18890SDaniel P. Berrange                          "PBKDF iterations %llu too large to scale",
13763bd18890SDaniel P. Berrange                          (unsigned long long)iters);
13773bd18890SDaniel P. Berrange         goto error;
13783bd18890SDaniel P. Berrange     }
13793bd18890SDaniel P. Berrange 
13803bd18890SDaniel P. Berrange     /* iter_time was in millis, but count_iters reported for secs */
13813bd18890SDaniel P. Berrange     iters = iters * luks_opts.iter_time / 1000;
13823bd18890SDaniel P. Berrange 
13833e308f20SDaniel P. Berrange     /* Why /= 8 ?  That matches cryptsetup, but there's no
13843e308f20SDaniel P. Berrange      * explanation why they chose /= 8... Probably so that
13853e308f20SDaniel P. Berrange      * if all 8 keyslots are active we only spend 1 second
13863e308f20SDaniel P. Berrange      * in total time to check all keys */
138759b060beSDaniel P. Berrange     iters /= 8;
138859b060beSDaniel P. Berrange     if (iters > UINT32_MAX) {
138959b060beSDaniel P. Berrange         error_setg_errno(errp, ERANGE,
139059b060beSDaniel P. Berrange                          "PBKDF iterations %llu larger than %u",
139159b060beSDaniel P. Berrange                          (unsigned long long)iters, UINT32_MAX);
139259b060beSDaniel P. Berrange         goto error;
139359b060beSDaniel P. Berrange     }
139459b060beSDaniel P. Berrange     iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS);
139559b060beSDaniel P. Berrange     luks->header.master_key_iterations = iters;
13963e308f20SDaniel P. Berrange 
13973e308f20SDaniel P. Berrange     /* Hash the master key, saving the result in the LUKS
13983e308f20SDaniel P. Berrange      * header. This hash is used when opening the encrypted
13993e308f20SDaniel P. Berrange      * device to verify that the user password unlocked a
14003e308f20SDaniel P. Berrange      * valid master key
14013e308f20SDaniel P. Berrange      */
14023e308f20SDaniel P. Berrange     if (qcrypto_pbkdf2(luks_opts.hash_alg,
1403f0d3c362SMaxim Levitsky                        masterkey, luks->header.master_key_len,
14043e308f20SDaniel P. Berrange                        luks->header.master_key_salt,
14053e308f20SDaniel P. Berrange                        QCRYPTO_BLOCK_LUKS_SALT_LEN,
14063e308f20SDaniel P. Berrange                        luks->header.master_key_iterations,
14073e308f20SDaniel P. Berrange                        luks->header.master_key_digest,
14083e308f20SDaniel P. Berrange                        QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
14093e308f20SDaniel P. Berrange                        errp) < 0) {
14103e308f20SDaniel P. Berrange         goto error;
14113e308f20SDaniel P. Berrange     }
14123e308f20SDaniel P. Berrange 
1413bd56a55aSMaxim Levitsky     /* start with the sector that follows the header*/
1414bd56a55aSMaxim Levitsky     header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
1415bd56a55aSMaxim Levitsky         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
14163e308f20SDaniel P. Berrange 
1417bd56a55aSMaxim Levitsky     split_key_sectors =
1418bd56a55aSMaxim Levitsky         qcrypto_block_luks_splitkeylen_sectors(luks,
1419bd56a55aSMaxim Levitsky                                                header_sectors,
1420bd56a55aSMaxim Levitsky                                                QCRYPTO_BLOCK_LUKS_STRIPES);
1421bd56a55aSMaxim Levitsky 
14223e308f20SDaniel P. Berrange     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1423bd56a55aSMaxim Levitsky         QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i];
1424bd56a55aSMaxim Levitsky         slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
14253e308f20SDaniel P. Berrange 
1426bd56a55aSMaxim Levitsky         slot->key_offset_sector = header_sectors + i * split_key_sectors;
1427bd56a55aSMaxim Levitsky         slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
14283e308f20SDaniel P. Berrange     }
14293e308f20SDaniel P. Berrange 
14303e308f20SDaniel P. Berrange     /* The total size of the LUKS headers is the partition header + key
14313e308f20SDaniel P. Berrange      * slot headers, rounded up to the nearest sector, combined with
14323e308f20SDaniel P. Berrange      * the size of each master key material region, also rounded up
14333e308f20SDaniel P. Berrange      * to the nearest sector */
1434bd56a55aSMaxim Levitsky     luks->header.payload_offset_sector = header_sectors +
1435bd56a55aSMaxim Levitsky             QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
14363e308f20SDaniel P. Berrange 
1437850f49deSDaniel P. Berrange     block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
1438f0d3c362SMaxim Levitsky     block->payload_offset = luks->header.payload_offset_sector *
1439850f49deSDaniel P. Berrange         block->sector_size;
14403e308f20SDaniel P. Berrange 
14413e308f20SDaniel P. Berrange     /* Reserve header space to match payload offset */
1442e4a3507eSDaniel P. Berrange     initfunc(block, block->payload_offset, opaque, &local_err);
14433e308f20SDaniel P. Berrange     if (local_err) {
14443e308f20SDaniel P. Berrange         error_propagate(errp, local_err);
14453e308f20SDaniel P. Berrange         goto error;
14463e308f20SDaniel P. Berrange     }
14473e308f20SDaniel P. Berrange 
14483e308f20SDaniel P. Berrange 
14493994a7c9SMaxim Levitsky     /* populate the slot 0 with the password encrypted master key*/
14503994a7c9SMaxim Levitsky     /* This will also store the header */
14513994a7c9SMaxim Levitsky     if (qcrypto_block_luks_store_key(block,
14523994a7c9SMaxim Levitsky                                      0,
14533994a7c9SMaxim Levitsky                                      password,
14543994a7c9SMaxim Levitsky                                      masterkey,
14553994a7c9SMaxim Levitsky                                      luks_opts.iter_time,
14563994a7c9SMaxim Levitsky                                      writefunc,
1457e4a3507eSDaniel P. Berrange                                      opaque,
14583994a7c9SMaxim Levitsky                                      errp) < 0) {
14593e308f20SDaniel P. Berrange         goto error;
14603e308f20SDaniel P. Berrange     }
14613e308f20SDaniel P. Berrange 
1462f0d3c362SMaxim Levitsky     memset(masterkey, 0, luks->header.master_key_len);
14633e308f20SDaniel P. Berrange 
14643e308f20SDaniel P. Berrange     return 0;
14653e308f20SDaniel P. Berrange 
14663e308f20SDaniel P. Berrange  error:
14673e308f20SDaniel P. Berrange     if (masterkey) {
1468f0d3c362SMaxim Levitsky         memset(masterkey, 0, luks->header.master_key_len);
14693e308f20SDaniel P. Berrange     }
14703e308f20SDaniel P. Berrange 
1471c972fa12SVladimir Sementsov-Ogievskiy     qcrypto_block_free_cipher(block);
1472b640adcaSVladimir Sementsov-Ogievskiy     qcrypto_ivgen_free(block->ivgen);
1473b640adcaSVladimir Sementsov-Ogievskiy 
14743e308f20SDaniel P. Berrange     g_free(luks);
14753e308f20SDaniel P. Berrange     return -1;
14763e308f20SDaniel P. Berrange }
14773e308f20SDaniel P. Berrange 
14783e308f20SDaniel P. Berrange 
147940c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block,
148040c85028SDaniel P. Berrange                                        QCryptoBlockInfo *info,
148140c85028SDaniel P. Berrange                                        Error **errp)
148240c85028SDaniel P. Berrange {
148340c85028SDaniel P. Berrange     QCryptoBlockLUKS *luks = block->opaque;
148440c85028SDaniel P. Berrange     QCryptoBlockInfoLUKSSlot *slot;
148540c85028SDaniel P. Berrange     QCryptoBlockInfoLUKSSlotList *slots = NULL, **prev = &info->u.luks.slots;
148640c85028SDaniel P. Berrange     size_t i;
148740c85028SDaniel P. Berrange 
148840c85028SDaniel P. Berrange     info->u.luks.cipher_alg = luks->cipher_alg;
148940c85028SDaniel P. Berrange     info->u.luks.cipher_mode = luks->cipher_mode;
149040c85028SDaniel P. Berrange     info->u.luks.ivgen_alg = luks->ivgen_alg;
149140c85028SDaniel P. Berrange     if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
149240c85028SDaniel P. Berrange         info->u.luks.has_ivgen_hash_alg = true;
149340c85028SDaniel P. Berrange         info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg;
149440c85028SDaniel P. Berrange     }
149540c85028SDaniel P. Berrange     info->u.luks.hash_alg = luks->hash_alg;
149640c85028SDaniel P. Berrange     info->u.luks.payload_offset = block->payload_offset;
149740c85028SDaniel P. Berrange     info->u.luks.master_key_iters = luks->header.master_key_iterations;
149840c85028SDaniel P. Berrange     info->u.luks.uuid = g_strndup((const char *)luks->header.uuid,
149940c85028SDaniel P. Berrange                                   sizeof(luks->header.uuid));
150040c85028SDaniel P. Berrange 
150140c85028SDaniel P. Berrange     for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
150240c85028SDaniel P. Berrange         slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1);
150340c85028SDaniel P. Berrange         *prev = slots;
150440c85028SDaniel P. Berrange 
150540c85028SDaniel P. Berrange         slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
150640c85028SDaniel P. Berrange         slot->active = luks->header.key_slots[i].active ==
150740c85028SDaniel P. Berrange             QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
1508f0d3c362SMaxim Levitsky         slot->key_offset = luks->header.key_slots[i].key_offset_sector
150940c85028SDaniel P. Berrange              * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
151040c85028SDaniel P. Berrange         if (slot->active) {
151140c85028SDaniel P. Berrange             slot->has_iters = true;
151240c85028SDaniel P. Berrange             slot->iters = luks->header.key_slots[i].iterations;
151340c85028SDaniel P. Berrange             slot->has_stripes = true;
151440c85028SDaniel P. Berrange             slot->stripes = luks->header.key_slots[i].stripes;
151540c85028SDaniel P. Berrange         }
151640c85028SDaniel P. Berrange 
151740c85028SDaniel P. Berrange         prev = &slots->next;
151840c85028SDaniel P. Berrange     }
151940c85028SDaniel P. Berrange 
152040c85028SDaniel P. Berrange     return 0;
152140c85028SDaniel P. Berrange }
152240c85028SDaniel P. Berrange 
152340c85028SDaniel P. Berrange 
15243e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
15253e308f20SDaniel P. Berrange {
15263e308f20SDaniel P. Berrange     g_free(block->opaque);
15273e308f20SDaniel P. Berrange }
15283e308f20SDaniel P. Berrange 
15293e308f20SDaniel P. Berrange 
15303e308f20SDaniel P. Berrange static int
15313e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block,
15324609742aSDaniel P. Berrange                            uint64_t offset,
15333e308f20SDaniel P. Berrange                            uint8_t *buf,
15343e308f20SDaniel P. Berrange                            size_t len,
15353e308f20SDaniel P. Berrange                            Error **errp)
15363e308f20SDaniel P. Berrange {
15374609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
15384609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
15390f0d596cSVladimir Sementsov-Ogievskiy     return qcrypto_block_decrypt_helper(block,
15403e308f20SDaniel P. Berrange                                         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
15414609742aSDaniel P. Berrange                                         offset, buf, len, errp);
15423e308f20SDaniel P. Berrange }
15433e308f20SDaniel P. Berrange 
15443e308f20SDaniel P. Berrange 
15453e308f20SDaniel P. Berrange static int
15463e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block,
15474609742aSDaniel P. Berrange                            uint64_t offset,
15483e308f20SDaniel P. Berrange                            uint8_t *buf,
15493e308f20SDaniel P. Berrange                            size_t len,
15503e308f20SDaniel P. Berrange                            Error **errp)
15513e308f20SDaniel P. Berrange {
15524609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
15534609742aSDaniel P. Berrange     assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
15540f0d596cSVladimir Sementsov-Ogievskiy     return qcrypto_block_encrypt_helper(block,
15553e308f20SDaniel P. Berrange                                         QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
15564609742aSDaniel P. Berrange                                         offset, buf, len, errp);
15573e308f20SDaniel P. Berrange }
15583e308f20SDaniel P. Berrange 
15593e308f20SDaniel P. Berrange 
15603e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = {
15613e308f20SDaniel P. Berrange     .open = qcrypto_block_luks_open,
15623e308f20SDaniel P. Berrange     .create = qcrypto_block_luks_create,
156340c85028SDaniel P. Berrange     .get_info = qcrypto_block_luks_get_info,
15643e308f20SDaniel P. Berrange     .cleanup = qcrypto_block_luks_cleanup,
15653e308f20SDaniel P. Berrange     .decrypt = qcrypto_block_luks_decrypt,
15663e308f20SDaniel P. Berrange     .encrypt = qcrypto_block_luks_encrypt,
15673e308f20SDaniel P. Berrange     .has_format = qcrypto_block_luks_has_format,
15683e308f20SDaniel P. Berrange };
1569