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"
2636445aceSDaniel P. Berrangé #include "block-luks-priv.h"
273e308f20SDaniel P. Berrange
283e308f20SDaniel P. Berrange #include "crypto/hash.h"
293e308f20SDaniel P. Berrange #include "crypto/afsplit.h"
303e308f20SDaniel P. Berrange #include "crypto/pbkdf.h"
313e308f20SDaniel P. Berrange #include "crypto/secret.h"
323e308f20SDaniel P. Berrange #include "crypto/random.h"
332ef950f9SFam Zheng #include "qemu/uuid.h"
343e308f20SDaniel P. Berrange
35557d2bdcSMaxim Levitsky #include "qemu/bitmap.h"
363e308f20SDaniel P. Berrange
373e308f20SDaniel P. Berrange /*
383e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is
393e308f20SDaniel P. Berrange *
403e308f20SDaniel P. Berrange * docs/on-disk-format.pdf
413e308f20SDaniel P. Berrange *
423e308f20SDaniel P. Berrange * in 'cryptsetup' package source code
433e308f20SDaniel P. Berrange *
443e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated
453e308f20SDaniel P. Berrange * Oct 16, 2011.
463e308f20SDaniel P. Berrange */
473e308f20SDaniel P. Berrange
483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS;
493e308f20SDaniel P. Berrange
503e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap;
513e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap {
523e308f20SDaniel P. Berrange const char *name;
533e308f20SDaniel P. Berrange int id;
543e308f20SDaniel P. Berrange };
553e308f20SDaniel P. Berrange
563e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap;
573e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap {
583e308f20SDaniel P. Berrange uint32_t key_bytes;
593e308f20SDaniel P. Berrange int id;
603e308f20SDaniel P. Berrange };
613e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap;
623e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap {
633e308f20SDaniel P. Berrange const char *name;
643e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes;
653e308f20SDaniel P. Berrange };
663e308f20SDaniel P. Berrange
673e308f20SDaniel P. Berrange
683e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
693e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = {
703e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 },
713e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 },
723e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 },
733e308f20SDaniel P. Berrange { 0, 0 },
743e308f20SDaniel P. Berrange };
753e308f20SDaniel P. Berrange
763e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
773e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = {
783e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 },
793e308f20SDaniel P. Berrange { 0, 0 },
803e308f20SDaniel P. Berrange };
813e308f20SDaniel P. Berrange
823e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
833e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = {
843e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 },
853e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 },
863e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 },
873e308f20SDaniel P. Berrange { 0, 0 },
883e308f20SDaniel P. Berrange };
893e308f20SDaniel P. Berrange
903e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap
913e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = {
923e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 },
933e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 },
943e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 },
953e308f20SDaniel P. Berrange { 0, 0 },
963e308f20SDaniel P. Berrange };
973e308f20SDaniel P. Berrange
9852ed9f45SHyman Huang #ifdef CONFIG_CRYPTO_SM4
9952ed9f45SHyman Huang static const QCryptoBlockLUKSCipherSizeMap
10052ed9f45SHyman Huang qcrypto_block_luks_cipher_size_map_sm4[] = {
10152ed9f45SHyman Huang { 16, QCRYPTO_CIPHER_ALG_SM4},
10252ed9f45SHyman Huang { 0, 0 },
10352ed9f45SHyman Huang };
10452ed9f45SHyman Huang #endif
10552ed9f45SHyman Huang
1063e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap
1073e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = {
1083e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes },
1093e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 },
1103e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent },
1113e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish },
11252ed9f45SHyman Huang #ifdef CONFIG_CRYPTO_SM4
11352ed9f45SHyman Huang { "sm4", qcrypto_block_luks_cipher_size_map_sm4},
11452ed9f45SHyman Huang #endif
1153e308f20SDaniel P. Berrange };
1163e308f20SDaniel P. Berrange
1173e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
1183e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592);
1193e308f20SDaniel P. Berrange
1203e308f20SDaniel P. Berrange
1213e308f20SDaniel P. Berrange struct QCryptoBlockLUKS {
1223e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header;
12340c85028SDaniel P. Berrange
1249d80e59dSMaxim Levitsky /* Main encryption algorithm used for encryption*/
12540c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg;
1269d80e59dSMaxim Levitsky
1279d80e59dSMaxim Levitsky /* Mode of encryption for the selected encryption algorithm */
12840c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode;
1299d80e59dSMaxim Levitsky
1309d80e59dSMaxim Levitsky /* Initialization vector generation algorithm */
13140c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg;
1329d80e59dSMaxim Levitsky
1339d80e59dSMaxim Levitsky /* Hash algorithm used for IV generation*/
13440c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg;
1359d80e59dSMaxim Levitsky
1369d80e59dSMaxim Levitsky /*
1379d80e59dSMaxim Levitsky * Encryption algorithm used for IV generation.
1389d80e59dSMaxim Levitsky * Usually the same as main encryption algorithm
1399d80e59dSMaxim Levitsky */
1409d80e59dSMaxim Levitsky QCryptoCipherAlgorithm ivgen_cipher_alg;
1419d80e59dSMaxim Levitsky
1429d80e59dSMaxim Levitsky /* Hash algorithm used in pbkdf2 function */
14340c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg;
144557d2bdcSMaxim Levitsky
145557d2bdcSMaxim Levitsky /* Name of the secret that was used to open the image */
146557d2bdcSMaxim Levitsky char *secret;
1473e308f20SDaniel P. Berrange };
1483e308f20SDaniel P. Berrange
1493e308f20SDaniel P. Berrange
qcrypto_block_luks_cipher_name_lookup(const char * name,QCryptoCipherMode mode,uint32_t key_bytes,Error ** errp)1503e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name,
1513e308f20SDaniel P. Berrange QCryptoCipherMode mode,
1523e308f20SDaniel P. Berrange uint32_t key_bytes,
1533e308f20SDaniel P. Berrange Error **errp)
1543e308f20SDaniel P. Berrange {
1553e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map =
1563e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map;
1573e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map);
1583e308f20SDaniel P. Berrange size_t i, j;
1593e308f20SDaniel P. Berrange
1603e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) {
1613e308f20SDaniel P. Berrange key_bytes /= 2;
1623e308f20SDaniel P. Berrange }
1633e308f20SDaniel P. Berrange
1643e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) {
1653e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) {
1663e308f20SDaniel P. Berrange continue;
1673e308f20SDaniel P. Berrange }
1683e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) {
1693e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) {
1703e308f20SDaniel P. Berrange return map[i].sizes[j].id;
1713e308f20SDaniel P. Berrange }
1723e308f20SDaniel P. Berrange }
1733e308f20SDaniel P. Berrange }
1743e308f20SDaniel P. Berrange
1756c198932SDaniel P. Berrangé error_setg(errp, "Algorithm '%s' with key size %d bytes not supported",
1763e308f20SDaniel P. Berrange name, key_bytes);
1773e308f20SDaniel P. Berrange return 0;
1783e308f20SDaniel P. Berrange }
1793e308f20SDaniel P. Berrange
1803e308f20SDaniel P. Berrange static const char *
qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,Error ** errp)1813e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg,
1823e308f20SDaniel P. Berrange Error **errp)
1833e308f20SDaniel P. Berrange {
1843e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map =
1853e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map;
1863e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map);
1873e308f20SDaniel P. Berrange size_t i, j;
1883e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) {
1893e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) {
1903e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) {
1913e308f20SDaniel P. Berrange return map[i].name;
1923e308f20SDaniel P. Berrange }
1933e308f20SDaniel P. Berrange }
1943e308f20SDaniel P. Berrange }
1953e308f20SDaniel P. Berrange
1963e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported",
197977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(alg));
1983e308f20SDaniel P. Berrange return NULL;
1993e308f20SDaniel P. Berrange }
2003e308f20SDaniel P. Berrange
2013e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can
2023e308f20SDaniel P. Berrange * make that function emit a more friendly error message */
qcrypto_block_luks_name_lookup(const char * name,const QEnumLookup * map,const char * type,Error ** errp)2033e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name,
204f7abe0ecSMarc-André Lureau const QEnumLookup *map,
2053e308f20SDaniel P. Berrange const char *type,
2063e308f20SDaniel P. Berrange Error **errp)
2073e308f20SDaniel P. Berrange {
2089ae33079SMarkus Armbruster int ret = qapi_enum_parse(map, name, -1, NULL);
2093e308f20SDaniel P. Berrange
2109ae33079SMarkus Armbruster if (ret < 0) {
2116c198932SDaniel P. Berrangé error_setg(errp, "%s '%s' not supported", type, name);
2123e308f20SDaniel P. Berrange return 0;
2133e308f20SDaniel P. Berrange }
2149ae33079SMarkus Armbruster return ret;
2159ae33079SMarkus Armbruster }
2163e308f20SDaniel P. Berrange
2173e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \
2183e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \
219f7abe0ecSMarc-André Lureau &QCryptoCipherMode_lookup, \
2203e308f20SDaniel P. Berrange "Cipher mode", \
2213e308f20SDaniel P. Berrange errp)
2223e308f20SDaniel P. Berrange
2233e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \
2243e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \
225f7abe0ecSMarc-André Lureau &QCryptoHashAlgorithm_lookup, \
2263e308f20SDaniel P. Berrange "Hash algorithm", \
2273e308f20SDaniel P. Berrange errp)
2283e308f20SDaniel P. Berrange
2293e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \
2303e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \
231f7abe0ecSMarc-André Lureau &QCryptoIVGenAlgorithm_lookup, \
2323e308f20SDaniel P. Berrange "IV generator", \
2333e308f20SDaniel P. Berrange errp)
2343e308f20SDaniel P. Berrange
2353e308f20SDaniel P. Berrange
2363e308f20SDaniel P. Berrange static bool
qcrypto_block_luks_has_format(const uint8_t * buf,size_t buf_size)2373e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf,
2383e308f20SDaniel P. Berrange size_t buf_size)
2393e308f20SDaniel P. Berrange {
2403e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf;
2413e308f20SDaniel P. Berrange
2423e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) &&
2433e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic,
2443e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 &&
2453e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) {
2463e308f20SDaniel P. Berrange return true;
2473e308f20SDaniel P. Berrange } else {
2483e308f20SDaniel P. Berrange return false;
2493e308f20SDaniel P. Berrange }
2503e308f20SDaniel P. Berrange }
2513e308f20SDaniel P. Berrange
2523e308f20SDaniel P. Berrange
2533e308f20SDaniel P. Berrange /**
2543e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV.
2553e308f20SDaniel P. Berrange *
2563e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV
2573e308f20SDaniel P. Berrange * may be different from the cipher length used for the block
2580a19d879SMichael Tokarev * encryption, because dm-crypt uses the hash digest length
2593e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher
2603e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as
2613e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest
2623e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined
2633e308f20SDaniel P. Berrange */
2643e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm
qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,QCryptoHashAlgorithm hash,Error ** errp)2653e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher,
2663e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash,
2673e308f20SDaniel P. Berrange Error **errp)
2683e308f20SDaniel P. Berrange {
2693e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash);
2703e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher);
2713e308f20SDaniel P. Berrange if (digestlen == keylen) {
2723e308f20SDaniel P. Berrange return cipher;
2733e308f20SDaniel P. Berrange }
2743e308f20SDaniel P. Berrange
2753e308f20SDaniel P. Berrange switch (cipher) {
2763e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128:
2773e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192:
2783e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256:
2793e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len(
2803e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) {
2813e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128;
2823e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len(
2833e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) {
2843e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192;
2853e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len(
2863e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) {
2873e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256;
2883e308f20SDaniel P. Berrange } else {
2893e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available",
2903e308f20SDaniel P. Berrange digestlen);
2913e308f20SDaniel P. Berrange return 0;
2923e308f20SDaniel P. Berrange }
2933e308f20SDaniel P. Berrange break;
2943e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128:
2953e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192:
2963e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256:
2973e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len(
2983e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) {
2993e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128;
3003e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len(
3013e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) {
3023e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192;
3033e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len(
3043e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) {
3053e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256;
3063e308f20SDaniel P. Berrange } else {
3073e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available",
3083e308f20SDaniel P. Berrange digestlen);
3093e308f20SDaniel P. Berrange return 0;
3103e308f20SDaniel P. Berrange }
3113e308f20SDaniel P. Berrange break;
3123e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128:
3133e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192:
3143e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256:
3153e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len(
3163e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) {
3173e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128;
3183e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len(
3193e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) {
3203e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192;
3213e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len(
3223e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) {
3233e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256;
3243e308f20SDaniel P. Berrange } else {
3253e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available",
3263e308f20SDaniel P. Berrange digestlen);
3273e308f20SDaniel P. Berrange return 0;
3283e308f20SDaniel P. Berrange }
3293e308f20SDaniel P. Berrange break;
3303e308f20SDaniel P. Berrange default:
3313e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv",
332977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(cipher));
3333e308f20SDaniel P. Berrange return 0;
3343e308f20SDaniel P. Berrange }
3353e308f20SDaniel P. Berrange }
3363e308f20SDaniel P. Berrange
3373e308f20SDaniel P. Berrange /*
338bd56a55aSMaxim Levitsky * Returns number of sectors needed to store the key material
339bd56a55aSMaxim Levitsky * given number of anti forensic stripes
340bd56a55aSMaxim Levitsky */
341bd56a55aSMaxim Levitsky static int
qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS * luks,unsigned int header_sectors,unsigned int stripes)342bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks,
343bd56a55aSMaxim Levitsky unsigned int header_sectors,
344bd56a55aSMaxim Levitsky unsigned int stripes)
345bd56a55aSMaxim Levitsky {
346bd56a55aSMaxim Levitsky /*
347bd56a55aSMaxim Levitsky * This calculation doesn't match that shown in the spec,
348bd56a55aSMaxim Levitsky * but instead follows the cryptsetup implementation.
349bd56a55aSMaxim Levitsky */
350bd56a55aSMaxim Levitsky
351bd56a55aSMaxim Levitsky size_t splitkeylen = luks->header.master_key_len * stripes;
352bd56a55aSMaxim Levitsky
353bd56a55aSMaxim Levitsky /* First align the key material size to block size*/
354bd56a55aSMaxim Levitsky size_t splitkeylen_sectors =
355bd56a55aSMaxim Levitsky DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE);
356bd56a55aSMaxim Levitsky
357bd56a55aSMaxim Levitsky /* Then also align the key material size to the size of the header */
358bd56a55aSMaxim Levitsky return ROUND_UP(splitkeylen_sectors, header_sectors);
359bd56a55aSMaxim Levitsky }
360bd56a55aSMaxim Levitsky
36198c72dfbSDaniel P. Berrangé
36298c72dfbSDaniel P. Berrangé void
qcrypto_block_luks_to_disk_endian(QCryptoBlockLUKSHeader * hdr)36398c72dfbSDaniel P. Berrangé qcrypto_block_luks_to_disk_endian(QCryptoBlockLUKSHeader *hdr)
36498c72dfbSDaniel P. Berrangé {
36598c72dfbSDaniel P. Berrangé size_t i;
36698c72dfbSDaniel P. Berrangé
36798c72dfbSDaniel P. Berrangé /*
36898c72dfbSDaniel P. Berrangé * Everything on disk uses Big Endian (tm), so flip header fields
36998c72dfbSDaniel P. Berrangé * before writing them
37098c72dfbSDaniel P. Berrangé */
37198c72dfbSDaniel P. Berrangé cpu_to_be16s(&hdr->version);
37298c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->payload_offset_sector);
37398c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->master_key_len);
37498c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->master_key_iterations);
37598c72dfbSDaniel P. Berrangé
37698c72dfbSDaniel P. Berrangé for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
37798c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].active);
37898c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].iterations);
37998c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].key_offset_sector);
38098c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].stripes);
38198c72dfbSDaniel P. Berrangé }
38298c72dfbSDaniel P. Berrangé }
38398c72dfbSDaniel P. Berrangé
38498c72dfbSDaniel P. Berrangé void
qcrypto_block_luks_from_disk_endian(QCryptoBlockLUKSHeader * hdr)38598c72dfbSDaniel P. Berrangé qcrypto_block_luks_from_disk_endian(QCryptoBlockLUKSHeader *hdr)
38698c72dfbSDaniel P. Berrangé {
38798c72dfbSDaniel P. Berrangé size_t i;
38898c72dfbSDaniel P. Berrangé
38998c72dfbSDaniel P. Berrangé /*
39098c72dfbSDaniel P. Berrangé * The header is always stored in big-endian format, so
39198c72dfbSDaniel P. Berrangé * convert everything to native
39298c72dfbSDaniel P. Berrangé */
39398c72dfbSDaniel P. Berrangé be16_to_cpus(&hdr->version);
39498c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->payload_offset_sector);
39598c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->master_key_len);
39698c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->master_key_iterations);
39798c72dfbSDaniel P. Berrangé
39898c72dfbSDaniel P. Berrangé for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
39998c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].active);
40098c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].iterations);
40198c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].key_offset_sector);
40298c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].stripes);
40398c72dfbSDaniel P. Berrangé }
40498c72dfbSDaniel P. Berrangé }
40598c72dfbSDaniel P. Berrangé
406bd56a55aSMaxim Levitsky /*
4070a19d879SMichael Tokarev * Stores the main LUKS header, taking care of endianness
408dde2c5afSMaxim Levitsky */
409dde2c5afSMaxim Levitsky static int
qcrypto_block_luks_store_header(QCryptoBlock * block,QCryptoBlockWriteFunc writefunc,void * opaque,Error ** errp)410dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block,
411dde2c5afSMaxim Levitsky QCryptoBlockWriteFunc writefunc,
412dde2c5afSMaxim Levitsky void *opaque,
413dde2c5afSMaxim Levitsky Error **errp)
414dde2c5afSMaxim Levitsky {
415dde2c5afSMaxim Levitsky const QCryptoBlockLUKS *luks = block->opaque;
416dde2c5afSMaxim Levitsky Error *local_err = NULL;
417dde2c5afSMaxim Levitsky g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL;
418dde2c5afSMaxim Levitsky
419dde2c5afSMaxim Levitsky /* Create a copy of the header */
420dde2c5afSMaxim Levitsky hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1);
421dde2c5afSMaxim Levitsky memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader));
422dde2c5afSMaxim Levitsky
42398c72dfbSDaniel P. Berrangé qcrypto_block_luks_to_disk_endian(hdr_copy);
424dde2c5afSMaxim Levitsky
425dde2c5afSMaxim Levitsky /* Write out the partition header and key slot headers */
426dde2c5afSMaxim Levitsky writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy),
427dde2c5afSMaxim Levitsky opaque, &local_err);
428dde2c5afSMaxim Levitsky
429dde2c5afSMaxim Levitsky if (local_err) {
430dde2c5afSMaxim Levitsky error_propagate(errp, local_err);
431dde2c5afSMaxim Levitsky return -1;
432dde2c5afSMaxim Levitsky }
433dde2c5afSMaxim Levitsky return 0;
434dde2c5afSMaxim Levitsky }
435dde2c5afSMaxim Levitsky
436dde2c5afSMaxim Levitsky /*
4370a19d879SMichael Tokarev * Loads the main LUKS header, and byteswaps it to native endianness
438dde2c5afSMaxim Levitsky * And run basic sanity checks on it
439dde2c5afSMaxim Levitsky */
440dde2c5afSMaxim Levitsky static int
qcrypto_block_luks_load_header(QCryptoBlock * block,QCryptoBlockReadFunc readfunc,void * opaque,Error ** errp)441dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block,
442dde2c5afSMaxim Levitsky QCryptoBlockReadFunc readfunc,
443dde2c5afSMaxim Levitsky void *opaque,
444dde2c5afSMaxim Levitsky Error **errp)
445dde2c5afSMaxim Levitsky {
446757dda54SAlberto Faria int rv;
447dde2c5afSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque;
448dde2c5afSMaxim Levitsky
449dde2c5afSMaxim Levitsky /*
450dde2c5afSMaxim Levitsky * Read the entire LUKS header, minus the key material from
451dde2c5afSMaxim Levitsky * the underlying device
452dde2c5afSMaxim Levitsky */
453dde2c5afSMaxim Levitsky rv = readfunc(block, 0,
454dde2c5afSMaxim Levitsky (uint8_t *)&luks->header,
455dde2c5afSMaxim Levitsky sizeof(luks->header),
456dde2c5afSMaxim Levitsky opaque,
457dde2c5afSMaxim Levitsky errp);
458dde2c5afSMaxim Levitsky if (rv < 0) {
459dde2c5afSMaxim Levitsky return rv;
460dde2c5afSMaxim Levitsky }
461dde2c5afSMaxim Levitsky
46298c72dfbSDaniel P. Berrangé qcrypto_block_luks_from_disk_endian(&luks->header);
463dde2c5afSMaxim Levitsky
464dde2c5afSMaxim Levitsky return 0;
465dde2c5afSMaxim Levitsky }
466dde2c5afSMaxim Levitsky
467dde2c5afSMaxim Levitsky /*
4689fa9c1c2SMaxim Levitsky * Does basic sanity checks on the LUKS header
4699fa9c1c2SMaxim Levitsky */
4709fa9c1c2SMaxim Levitsky static int
qcrypto_block_luks_check_header(const QCryptoBlockLUKS * luks,unsigned int flags,Error ** errp)4719ad5c4e7SHyman Huang qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks,
4729ad5c4e7SHyman Huang unsigned int flags,
4739ad5c4e7SHyman Huang Error **errp)
4749fa9c1c2SMaxim Levitsky {
475befdba9eSMaxim Levitsky size_t i, j;
476befdba9eSMaxim Levitsky
477befdba9eSMaxim Levitsky unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
478befdba9eSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
4799ad5c4e7SHyman Huang bool detached = flags & QCRYPTO_BLOCK_OPEN_DETACHED;
480befdba9eSMaxim Levitsky
4819fa9c1c2SMaxim Levitsky if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
4829fa9c1c2SMaxim Levitsky QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
4839fa9c1c2SMaxim Levitsky error_setg(errp, "Volume is not in LUKS format");
4849fa9c1c2SMaxim Levitsky return -1;
4859fa9c1c2SMaxim Levitsky }
4869fa9c1c2SMaxim Levitsky
4879fa9c1c2SMaxim Levitsky if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) {
4889fa9c1c2SMaxim Levitsky error_setg(errp, "LUKS version %" PRIu32 " is not supported",
4899fa9c1c2SMaxim Levitsky luks->header.version);
4909fa9c1c2SMaxim Levitsky return -1;
4919fa9c1c2SMaxim Levitsky }
492befdba9eSMaxim Levitsky
493c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_name, '\0',
494c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_name))) {
495c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher name is not NUL terminated");
496c1d8634cSDaniel P. Berrangé return -1;
497c1d8634cSDaniel P. Berrangé }
498c1d8634cSDaniel P. Berrangé
499c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_mode, '\0',
500c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_mode))) {
501c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher mode is not NUL terminated");
502c1d8634cSDaniel P. Berrangé return -1;
503c1d8634cSDaniel P. Berrangé }
504c1d8634cSDaniel P. Berrangé
505c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.hash_spec, '\0',
506c1d8634cSDaniel P. Berrangé sizeof(luks->header.hash_spec))) {
507c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header hash spec is not NUL terminated");
508c1d8634cSDaniel P. Berrangé return -1;
509c1d8634cSDaniel P. Berrangé }
510c1d8634cSDaniel P. Berrangé
5119ad5c4e7SHyman Huang if (!detached && luks->header.payload_offset_sector <
512d233fbc3SDaniel P. Berrangé DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET,
513d233fbc3SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) {
514d233fbc3SDaniel P. Berrangé error_setg(errp, "LUKS payload is overlapping with the header");
515d233fbc3SDaniel P. Berrangé return -1;
516d233fbc3SDaniel P. Berrangé }
517d233fbc3SDaniel P. Berrangé
518b57151acSDaniel P. Berrangé if (luks->header.master_key_iterations == 0) {
519b57151acSDaniel P. Berrangé error_setg(errp, "LUKS key iteration count is zero");
520b57151acSDaniel P. Berrangé return -1;
521b57151acSDaniel P. Berrangé }
522b57151acSDaniel P. Berrangé
523befdba9eSMaxim Levitsky /* Check all keyslots for corruption */
524befdba9eSMaxim Levitsky for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) {
525befdba9eSMaxim Levitsky
526befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i];
527befdba9eSMaxim Levitsky unsigned int start1 = slot1->key_offset_sector;
528befdba9eSMaxim Levitsky unsigned int len1 =
529befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks,
530befdba9eSMaxim Levitsky header_sectors,
531befdba9eSMaxim Levitsky slot1->stripes);
532befdba9eSMaxim Levitsky
533f1195961SDaniel P. Berrangé if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) {
534f1195961SDaniel P. Berrangé error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)",
535f1195961SDaniel P. Berrangé i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES);
536befdba9eSMaxim Levitsky return -1;
537befdba9eSMaxim Levitsky }
538befdba9eSMaxim Levitsky
539befdba9eSMaxim Levitsky if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED &&
540befdba9eSMaxim Levitsky slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
541befdba9eSMaxim Levitsky error_setg(errp,
542befdba9eSMaxim Levitsky "Keyslot %zu state (active/disable) is corrupted", i);
543befdba9eSMaxim Levitsky return -1;
544befdba9eSMaxim Levitsky }
545befdba9eSMaxim Levitsky
546b57151acSDaniel P. Berrangé if (slot1->active == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED &&
547b57151acSDaniel P. Berrangé slot1->iterations == 0) {
548b57151acSDaniel P. Berrangé error_setg(errp, "Keyslot %zu iteration count is zero", i);
549b57151acSDaniel P. Berrangé return -1;
550b57151acSDaniel P. Berrangé }
551b57151acSDaniel P. Berrangé
552c5f69628SDaniel P. Berrangé if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET,
55393569c37SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) {
55493569c37SDaniel P. Berrangé error_setg(errp,
55593569c37SDaniel P. Berrangé "Keyslot %zu is overlapping with the LUKS header",
55693569c37SDaniel P. Berrangé i);
55793569c37SDaniel P. Berrangé return -1;
55893569c37SDaniel P. Berrangé }
55993569c37SDaniel P. Berrangé
5609ad5c4e7SHyman Huang if (!detached && start1 + len1 > luks->header.payload_offset_sector) {
561befdba9eSMaxim Levitsky error_setg(errp,
562befdba9eSMaxim Levitsky "Keyslot %zu is overlapping with the encrypted payload",
563befdba9eSMaxim Levitsky i);
564befdba9eSMaxim Levitsky return -1;
565befdba9eSMaxim Levitsky }
566befdba9eSMaxim Levitsky
567befdba9eSMaxim Levitsky for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) {
568befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j];
569befdba9eSMaxim Levitsky unsigned int start2 = slot2->key_offset_sector;
570befdba9eSMaxim Levitsky unsigned int len2 =
571befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks,
572befdba9eSMaxim Levitsky header_sectors,
573befdba9eSMaxim Levitsky slot2->stripes);
574befdba9eSMaxim Levitsky
575befdba9eSMaxim Levitsky if (start1 + len1 > start2 && start2 + len2 > start1) {
576befdba9eSMaxim Levitsky error_setg(errp,
577befdba9eSMaxim Levitsky "Keyslots %zu and %zu are overlapping in the header",
578befdba9eSMaxim Levitsky i, j);
579befdba9eSMaxim Levitsky return -1;
580befdba9eSMaxim Levitsky }
581befdba9eSMaxim Levitsky }
582befdba9eSMaxim Levitsky
583befdba9eSMaxim Levitsky }
5849fa9c1c2SMaxim Levitsky return 0;
5859fa9c1c2SMaxim Levitsky }
5869fa9c1c2SMaxim Levitsky
5879fa9c1c2SMaxim Levitsky /*
5889fa9c1c2SMaxim Levitsky * Parses the crypto parameters that are stored in the LUKS header
5899fa9c1c2SMaxim Levitsky */
5909fa9c1c2SMaxim Levitsky
5919fa9c1c2SMaxim Levitsky static int
qcrypto_block_luks_parse_header(QCryptoBlockLUKS * luks,Error ** errp)5929fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp)
5939fa9c1c2SMaxim Levitsky {
5949fa9c1c2SMaxim Levitsky g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode);
5959fa9c1c2SMaxim Levitsky char *ivgen_name, *ivhash_name;
5969fa9c1c2SMaxim Levitsky Error *local_err = NULL;
5979fa9c1c2SMaxim Levitsky
5989fa9c1c2SMaxim Levitsky /*
5999fa9c1c2SMaxim Levitsky * The cipher_mode header contains a string that we have
6009fa9c1c2SMaxim Levitsky * to further parse, of the format
6019fa9c1c2SMaxim Levitsky *
6029fa9c1c2SMaxim Levitsky * <cipher-mode>-<iv-generator>[:<iv-hash>]
6039fa9c1c2SMaxim Levitsky *
6049fa9c1c2SMaxim Levitsky * eg cbc-essiv:sha256, cbc-plain64
6059fa9c1c2SMaxim Levitsky */
6069fa9c1c2SMaxim Levitsky ivgen_name = strchr(cipher_mode, '-');
6079fa9c1c2SMaxim Levitsky if (!ivgen_name) {
6086c198932SDaniel P. Berrangé error_setg(errp, "Unexpected cipher mode string format '%s'",
6099fa9c1c2SMaxim Levitsky luks->header.cipher_mode);
6109fa9c1c2SMaxim Levitsky return -1;
6119fa9c1c2SMaxim Levitsky }
6129fa9c1c2SMaxim Levitsky *ivgen_name = '\0';
6139fa9c1c2SMaxim Levitsky ivgen_name++;
6149fa9c1c2SMaxim Levitsky
6159fa9c1c2SMaxim Levitsky ivhash_name = strchr(ivgen_name, ':');
6169fa9c1c2SMaxim Levitsky if (!ivhash_name) {
6179fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = 0;
6189fa9c1c2SMaxim Levitsky } else {
6199fa9c1c2SMaxim Levitsky *ivhash_name = '\0';
6209fa9c1c2SMaxim Levitsky ivhash_name++;
6219fa9c1c2SMaxim Levitsky
6229fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name,
6239fa9c1c2SMaxim Levitsky &local_err);
6249fa9c1c2SMaxim Levitsky if (local_err) {
6259fa9c1c2SMaxim Levitsky error_propagate(errp, local_err);
6269fa9c1c2SMaxim Levitsky return -1;
6279fa9c1c2SMaxim Levitsky }
6289fa9c1c2SMaxim Levitsky }
6299fa9c1c2SMaxim Levitsky
6309fa9c1c2SMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode,
6319fa9c1c2SMaxim Levitsky &local_err);
6329fa9c1c2SMaxim Levitsky if (local_err) {
6339fa9c1c2SMaxim Levitsky error_propagate(errp, local_err);
6349fa9c1c2SMaxim Levitsky return -1;
6359fa9c1c2SMaxim Levitsky }
6369fa9c1c2SMaxim Levitsky
6379fa9c1c2SMaxim Levitsky luks->cipher_alg =
6389fa9c1c2SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name,
6399fa9c1c2SMaxim Levitsky luks->cipher_mode,
6409fa9c1c2SMaxim Levitsky luks->header.master_key_len,
6419fa9c1c2SMaxim Levitsky &local_err);
6429fa9c1c2SMaxim Levitsky if (local_err) {
6439fa9c1c2SMaxim Levitsky error_propagate(errp, local_err);
6449fa9c1c2SMaxim Levitsky return -1;
6459fa9c1c2SMaxim Levitsky }
6469fa9c1c2SMaxim Levitsky
6479fa9c1c2SMaxim Levitsky luks->hash_alg =
6489fa9c1c2SMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec,
6499fa9c1c2SMaxim Levitsky &local_err);
6509fa9c1c2SMaxim Levitsky if (local_err) {
6519fa9c1c2SMaxim Levitsky error_propagate(errp, local_err);
6529fa9c1c2SMaxim Levitsky return -1;
6539fa9c1c2SMaxim Levitsky }
6549fa9c1c2SMaxim Levitsky
6559fa9c1c2SMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name,
6569fa9c1c2SMaxim Levitsky &local_err);
6579fa9c1c2SMaxim Levitsky if (local_err) {
6589fa9c1c2SMaxim Levitsky error_propagate(errp, local_err);
6599fa9c1c2SMaxim Levitsky return -1;
6609fa9c1c2SMaxim Levitsky }
6619fa9c1c2SMaxim Levitsky
6629fa9c1c2SMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
6639fa9c1c2SMaxim Levitsky if (!ivhash_name) {
6649fa9c1c2SMaxim Levitsky error_setg(errp, "Missing IV generator hash specification");
6659fa9c1c2SMaxim Levitsky return -1;
6669fa9c1c2SMaxim Levitsky }
6679fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg =
6689fa9c1c2SMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg,
6699fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg,
6709fa9c1c2SMaxim Levitsky &local_err);
6719fa9c1c2SMaxim Levitsky if (local_err) {
6729fa9c1c2SMaxim Levitsky error_propagate(errp, local_err);
6739fa9c1c2SMaxim Levitsky return -1;
6749fa9c1c2SMaxim Levitsky }
6759fa9c1c2SMaxim Levitsky } else {
6769fa9c1c2SMaxim Levitsky
6779fa9c1c2SMaxim Levitsky /*
6789fa9c1c2SMaxim Levitsky * Note we parsed the ivhash_name earlier in the cipher_mode
6799fa9c1c2SMaxim Levitsky * spec string even with plain/plain64 ivgens, but we
6809fa9c1c2SMaxim Levitsky * will ignore it, since it is irrelevant for these ivgens.
6819fa9c1c2SMaxim Levitsky * This is for compat with dm-crypt which will silently
6829fa9c1c2SMaxim Levitsky * ignore hash names with these ivgens rather than report
6839fa9c1c2SMaxim Levitsky * an error about the invalid usage
6849fa9c1c2SMaxim Levitsky */
6859fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg;
6869fa9c1c2SMaxim Levitsky }
6879fa9c1c2SMaxim Levitsky return 0;
6889fa9c1c2SMaxim Levitsky }
6899fa9c1c2SMaxim Levitsky
6909fa9c1c2SMaxim Levitsky /*
6913994a7c9SMaxim Levitsky * Given a key slot, user password, and the master key,
6923994a7c9SMaxim Levitsky * will store the encrypted master key there, and update the
6933994a7c9SMaxim Levitsky * in-memory header. User must then write the in-memory header
6943994a7c9SMaxim Levitsky *
6953994a7c9SMaxim Levitsky * Returns:
6963994a7c9SMaxim Levitsky * 0 if the keyslot was written successfully
6973994a7c9SMaxim Levitsky * with the provided password
6983994a7c9SMaxim Levitsky * -1 if a fatal error occurred while storing the key
6993994a7c9SMaxim Levitsky */
7003994a7c9SMaxim Levitsky static int
qcrypto_block_luks_store_key(QCryptoBlock * block,unsigned int slot_idx,const char * password,uint8_t * masterkey,uint64_t iter_time,QCryptoBlockWriteFunc writefunc,void * opaque,Error ** errp)7013994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block,
7023994a7c9SMaxim Levitsky unsigned int slot_idx,
7033994a7c9SMaxim Levitsky const char *password,
7043994a7c9SMaxim Levitsky uint8_t *masterkey,
7053994a7c9SMaxim Levitsky uint64_t iter_time,
7063994a7c9SMaxim Levitsky QCryptoBlockWriteFunc writefunc,
7073994a7c9SMaxim Levitsky void *opaque,
7083994a7c9SMaxim Levitsky Error **errp)
7093994a7c9SMaxim Levitsky {
7103994a7c9SMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque;
711557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot;
7123994a7c9SMaxim Levitsky g_autofree uint8_t *splitkey = NULL;
7133994a7c9SMaxim Levitsky size_t splitkeylen;
7143994a7c9SMaxim Levitsky g_autofree uint8_t *slotkey = NULL;
7153994a7c9SMaxim Levitsky g_autoptr(QCryptoCipher) cipher = NULL;
7163994a7c9SMaxim Levitsky g_autoptr(QCryptoIVGen) ivgen = NULL;
7173994a7c9SMaxim Levitsky Error *local_err = NULL;
7183994a7c9SMaxim Levitsky uint64_t iters;
7193994a7c9SMaxim Levitsky int ret = -1;
7203994a7c9SMaxim Levitsky
721557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
722557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx];
72355a01cabSAkihiko Odaki splitkeylen = luks->header.master_key_len * slot->stripes;
72455a01cabSAkihiko Odaki
7253994a7c9SMaxim Levitsky if (qcrypto_random_bytes(slot->salt,
7263994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN,
7273994a7c9SMaxim Levitsky errp) < 0) {
7283994a7c9SMaxim Levitsky goto cleanup;
7293994a7c9SMaxim Levitsky }
7303994a7c9SMaxim Levitsky
7313994a7c9SMaxim Levitsky /*
7323994a7c9SMaxim Levitsky * Determine how many iterations are required to
7333994a7c9SMaxim Levitsky * hash the user password while consuming 1 second of compute
7343994a7c9SMaxim Levitsky * time
7353994a7c9SMaxim Levitsky */
7363994a7c9SMaxim Levitsky iters = qcrypto_pbkdf2_count_iters(luks->hash_alg,
7373994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password),
7383994a7c9SMaxim Levitsky slot->salt,
7393994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN,
7403994a7c9SMaxim Levitsky luks->header.master_key_len,
7413994a7c9SMaxim Levitsky &local_err);
7423994a7c9SMaxim Levitsky if (local_err) {
7433994a7c9SMaxim Levitsky error_propagate(errp, local_err);
7443994a7c9SMaxim Levitsky goto cleanup;
7453994a7c9SMaxim Levitsky }
7463994a7c9SMaxim Levitsky
7473994a7c9SMaxim Levitsky if (iters > (ULLONG_MAX / iter_time)) {
7483994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE,
7493994a7c9SMaxim Levitsky "PBKDF iterations %llu too large to scale",
7503994a7c9SMaxim Levitsky (unsigned long long)iters);
7513994a7c9SMaxim Levitsky goto cleanup;
7523994a7c9SMaxim Levitsky }
7533994a7c9SMaxim Levitsky
7543994a7c9SMaxim Levitsky /* iter_time was in millis, but count_iters reported for secs */
7553994a7c9SMaxim Levitsky iters = iters * iter_time / 1000;
7563994a7c9SMaxim Levitsky
7573994a7c9SMaxim Levitsky if (iters > UINT32_MAX) {
7583994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE,
7593994a7c9SMaxim Levitsky "PBKDF iterations %llu larger than %u",
7603994a7c9SMaxim Levitsky (unsigned long long)iters, UINT32_MAX);
7613994a7c9SMaxim Levitsky goto cleanup;
7623994a7c9SMaxim Levitsky }
7633994a7c9SMaxim Levitsky
7643994a7c9SMaxim Levitsky slot->iterations =
7653994a7c9SMaxim Levitsky MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS);
7663994a7c9SMaxim Levitsky
7673994a7c9SMaxim Levitsky
7683994a7c9SMaxim Levitsky /*
7693994a7c9SMaxim Levitsky * Generate a key that we'll use to encrypt the master
7703994a7c9SMaxim Levitsky * key, from the user's password
7713994a7c9SMaxim Levitsky */
7723994a7c9SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len);
7733994a7c9SMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg,
7743994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password),
7753994a7c9SMaxim Levitsky slot->salt,
7763994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN,
7773994a7c9SMaxim Levitsky slot->iterations,
7783994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len,
7793994a7c9SMaxim Levitsky errp) < 0) {
7803994a7c9SMaxim Levitsky goto cleanup;
7813994a7c9SMaxim Levitsky }
7823994a7c9SMaxim Levitsky
7833994a7c9SMaxim Levitsky
7843994a7c9SMaxim Levitsky /*
7853994a7c9SMaxim Levitsky * Setup the encryption objects needed to encrypt the
7863994a7c9SMaxim Levitsky * master key material
7873994a7c9SMaxim Levitsky */
7883994a7c9SMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg,
7893994a7c9SMaxim Levitsky luks->cipher_mode,
7903994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len,
7913994a7c9SMaxim Levitsky errp);
7923994a7c9SMaxim Levitsky if (!cipher) {
7933994a7c9SMaxim Levitsky goto cleanup;
7943994a7c9SMaxim Levitsky }
7953994a7c9SMaxim Levitsky
7963994a7c9SMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
7973994a7c9SMaxim Levitsky luks->ivgen_cipher_alg,
7983994a7c9SMaxim Levitsky luks->ivgen_hash_alg,
7993994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len,
8003994a7c9SMaxim Levitsky errp);
8013994a7c9SMaxim Levitsky if (!ivgen) {
8023994a7c9SMaxim Levitsky goto cleanup;
8033994a7c9SMaxim Levitsky }
8043994a7c9SMaxim Levitsky
8053994a7c9SMaxim Levitsky /*
8063994a7c9SMaxim Levitsky * Before storing the master key, we need to vastly
8073994a7c9SMaxim Levitsky * increase its size, as protection against forensic
8083994a7c9SMaxim Levitsky * disk data recovery
8093994a7c9SMaxim Levitsky */
8103994a7c9SMaxim Levitsky splitkey = g_new0(uint8_t, splitkeylen);
8113994a7c9SMaxim Levitsky
8123994a7c9SMaxim Levitsky if (qcrypto_afsplit_encode(luks->hash_alg,
8133994a7c9SMaxim Levitsky luks->header.master_key_len,
8143994a7c9SMaxim Levitsky slot->stripes,
8153994a7c9SMaxim Levitsky masterkey,
8163994a7c9SMaxim Levitsky splitkey,
8173994a7c9SMaxim Levitsky errp) < 0) {
8183994a7c9SMaxim Levitsky goto cleanup;
8193994a7c9SMaxim Levitsky }
8203994a7c9SMaxim Levitsky
8213994a7c9SMaxim Levitsky /*
8223994a7c9SMaxim Levitsky * Now we encrypt the split master key with the key generated
8233994a7c9SMaxim Levitsky * from the user's password, before storing it
8243994a7c9SMaxim Levitsky */
8253994a7c9SMaxim Levitsky if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen,
8263994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
8273994a7c9SMaxim Levitsky 0,
8283994a7c9SMaxim Levitsky splitkey,
8293994a7c9SMaxim Levitsky splitkeylen,
8303994a7c9SMaxim Levitsky errp) < 0) {
8313994a7c9SMaxim Levitsky goto cleanup;
8323994a7c9SMaxim Levitsky }
8333994a7c9SMaxim Levitsky
8343994a7c9SMaxim Levitsky /* Write out the slot's master key material. */
8353994a7c9SMaxim Levitsky if (writefunc(block,
8363994a7c9SMaxim Levitsky slot->key_offset_sector *
8373994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
8383994a7c9SMaxim Levitsky splitkey, splitkeylen,
8393994a7c9SMaxim Levitsky opaque,
840757dda54SAlberto Faria errp) < 0) {
8413994a7c9SMaxim Levitsky goto cleanup;
8423994a7c9SMaxim Levitsky }
8433994a7c9SMaxim Levitsky
8443994a7c9SMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
8453994a7c9SMaxim Levitsky
8463994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) {
8473994a7c9SMaxim Levitsky goto cleanup;
8483994a7c9SMaxim Levitsky }
8493994a7c9SMaxim Levitsky
8503994a7c9SMaxim Levitsky ret = 0;
8513994a7c9SMaxim Levitsky
8523994a7c9SMaxim Levitsky cleanup:
8533994a7c9SMaxim Levitsky if (slotkey) {
8543994a7c9SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len);
8553994a7c9SMaxim Levitsky }
8563994a7c9SMaxim Levitsky if (splitkey) {
8573994a7c9SMaxim Levitsky memset(splitkey, 0, splitkeylen);
8583994a7c9SMaxim Levitsky }
8593994a7c9SMaxim Levitsky return ret;
8603994a7c9SMaxim Levitsky }
8613994a7c9SMaxim Levitsky
8623994a7c9SMaxim Levitsky /*
8633e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock
8643e308f20SDaniel P. Berrange * the master encryption key from the key slot.
8653e308f20SDaniel P. Berrange *
8663e308f20SDaniel P. Berrange * Returns:
8673e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted
8683e308f20SDaniel P. Berrange * with the provided password
8693e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully
8703e308f20SDaniel P. Berrange * with the provided password
8713e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key
8723e308f20SDaniel P. Berrange */
8733e308f20SDaniel P. Berrange static int
qcrypto_block_luks_load_key(QCryptoBlock * block,size_t slot_idx,const char * password,uint8_t * masterkey,QCryptoBlockReadFunc readfunc,void * opaque,Error ** errp)8743e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block,
8757e60a6f5SMaxim Levitsky size_t slot_idx,
8763e308f20SDaniel P. Berrange const char *password,
8773e308f20SDaniel P. Berrange uint8_t *masterkey,
8783e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc,
8793e308f20SDaniel P. Berrange void *opaque,
8803e308f20SDaniel P. Berrange Error **errp)
8813e308f20SDaniel P. Berrange {
8823e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque;
883557d2bdcSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot;
88457b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL;
8853e308f20SDaniel P. Berrange size_t splitkeylen;
88657b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL;
887757dda54SAlberto Faria int rv;
88857b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL;
8893e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
89057b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL;
8913e308f20SDaniel P. Berrange size_t niv;
8923e308f20SDaniel P. Berrange
893557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
894557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx];
8953e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
8963e308f20SDaniel P. Berrange return 0;
8973e308f20SDaniel P. Berrange }
8983e308f20SDaniel P. Berrange
8991ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes;
9003e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen);
9011ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len);
9023e308f20SDaniel P. Berrange
9033e308f20SDaniel P. Berrange /*
9043e308f20SDaniel P. Berrange * The user password is used to generate a (possible)
9053e308f20SDaniel P. Berrange * decryption key. This may or may not successfully
9063e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume
9073e308f20SDaniel P. Berrange * the key is correct and validate the results of
9083e308f20SDaniel P. Berrange * decryption later.
9093e308f20SDaniel P. Berrange */
9109d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg,
9113e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password),
9123e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN,
9133e308f20SDaniel P. Berrange slot->iterations,
9141ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len,
9153e308f20SDaniel P. Berrange errp) < 0) {
91657b9f113SDaniel P. Berrangé return -1;
9173e308f20SDaniel P. Berrange }
9183e308f20SDaniel P. Berrange
9193e308f20SDaniel P. Berrange /*
9203e308f20SDaniel P. Berrange * We need to read the master key material from the
9213e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is
9223e308f20SDaniel P. Berrange * not the raw master key, but rather the data after
9233e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result
9243e308f20SDaniel P. Berrange * then encrypted.
9253e308f20SDaniel P. Berrange */
9263e308f20SDaniel P. Berrange rv = readfunc(block,
927f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
9283e308f20SDaniel P. Berrange splitkey, splitkeylen,
929e4a3507eSDaniel P. Berrange opaque,
93037509233SFam Zheng errp);
9313e308f20SDaniel P. Berrange if (rv < 0) {
93257b9f113SDaniel P. Berrangé return -1;
9333e308f20SDaniel P. Berrange }
9343e308f20SDaniel P. Berrange
9353e308f20SDaniel P. Berrange
9363e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt
9373e308f20SDaniel P. Berrange * the split master key material */
9389d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg,
9399d80e59dSMaxim Levitsky luks->cipher_mode,
9409d80e59dSMaxim Levitsky possiblekey,
9419d80e59dSMaxim Levitsky luks->header.master_key_len,
9423e308f20SDaniel P. Berrange errp);
9433e308f20SDaniel P. Berrange if (!cipher) {
94457b9f113SDaniel P. Berrangé return -1;
9453e308f20SDaniel P. Berrange }
9463e308f20SDaniel P. Berrange
9479d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
9489d80e59dSMaxim Levitsky luks->cipher_mode);
9499d80e59dSMaxim Levitsky
9509d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
9519d80e59dSMaxim Levitsky luks->ivgen_cipher_alg,
9529d80e59dSMaxim Levitsky luks->ivgen_hash_alg,
9539d80e59dSMaxim Levitsky possiblekey,
9549d80e59dSMaxim Levitsky luks->header.master_key_len,
9553e308f20SDaniel P. Berrange errp);
9563e308f20SDaniel P. Berrange if (!ivgen) {
95757b9f113SDaniel P. Berrangé return -1;
9583e308f20SDaniel P. Berrange }
9593e308f20SDaniel P. Berrange
9603e308f20SDaniel P. Berrange
9613e308f20SDaniel P. Berrange /*
9623e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same
9633e308f20SDaniel P. Berrange * way that the block device payload will be decrypted
9643e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator
9653e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master
9663e308f20SDaniel P. Berrange * key crosses a sector boundary.
9673e308f20SDaniel P. Berrange */
9680270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher,
9693e308f20SDaniel P. Berrange niv,
9703e308f20SDaniel P. Berrange ivgen,
9713e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
9723e308f20SDaniel P. Berrange 0,
9733e308f20SDaniel P. Berrange splitkey,
9743e308f20SDaniel P. Berrange splitkeylen,
9753e308f20SDaniel P. Berrange errp) < 0) {
97657b9f113SDaniel P. Berrangé return -1;
9773e308f20SDaniel P. Berrange }
9783e308f20SDaniel P. Berrange
9793e308f20SDaniel P. Berrange /*
9803e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join
9813e308f20SDaniel P. Berrange * it back together to get the actual master key.
9823e308f20SDaniel P. Berrange */
9839d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg,
9841ddd52e4SMaxim Levitsky luks->header.master_key_len,
9853e308f20SDaniel P. Berrange slot->stripes,
9863e308f20SDaniel P. Berrange splitkey,
9873e308f20SDaniel P. Berrange masterkey,
9883e308f20SDaniel P. Berrange errp) < 0) {
98957b9f113SDaniel P. Berrangé return -1;
9903e308f20SDaniel P. Berrange }
9913e308f20SDaniel P. Berrange
9923e308f20SDaniel P. Berrange
9933e308f20SDaniel P. Berrange /*
9943e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid,
9953e308f20SDaniel P. Berrange * because we just blindly assumed the user's password
9963e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are
9973e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and
9983e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot
9993e308f20SDaniel P. Berrange * header
10003e308f20SDaniel P. Berrange */
10019d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg,
10021ddd52e4SMaxim Levitsky masterkey,
10031ddd52e4SMaxim Levitsky luks->header.master_key_len,
10043e308f20SDaniel P. Berrange luks->header.master_key_salt,
10053e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN,
10063e308f20SDaniel P. Berrange luks->header.master_key_iterations,
10071ddd52e4SMaxim Levitsky keydigest,
10081ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest),
10093e308f20SDaniel P. Berrange errp) < 0) {
101057b9f113SDaniel P. Berrangé return -1;
10113e308f20SDaniel P. Berrange }
10123e308f20SDaniel P. Berrange
10133e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest,
10143e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) {
10153e308f20SDaniel P. Berrange /* Success, we got the right master key */
101657b9f113SDaniel P. Berrangé return 1;
10173e308f20SDaniel P. Berrange }
10183e308f20SDaniel P. Berrange
10193e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot,
10203e308f20SDaniel P. Berrange * tell caller to try another slot */
102157b9f113SDaniel P. Berrangé return 0;
10223e308f20SDaniel P. Berrange }
10233e308f20SDaniel P. Berrange
10243e308f20SDaniel P. Berrange
10253e308f20SDaniel P. Berrange /*
10263e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key
10273e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the
10283e308f20SDaniel P. Berrange * password until it successfully obtains a master key.
10293e308f20SDaniel P. Berrange *
10303e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded
10313e308f20SDaniel P. Berrange */
10323e308f20SDaniel P. Berrange static int
qcrypto_block_luks_find_key(QCryptoBlock * block,const char * password,uint8_t * masterkey,QCryptoBlockReadFunc readfunc,void * opaque,Error ** errp)10333e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block,
10343e308f20SDaniel P. Berrange const char *password,
10351ddd52e4SMaxim Levitsky uint8_t *masterkey,
10363e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc,
10373e308f20SDaniel P. Berrange void *opaque,
10383e308f20SDaniel P. Berrange Error **errp)
10393e308f20SDaniel P. Berrange {
10403e308f20SDaniel P. Berrange size_t i;
10413e308f20SDaniel P. Berrange int rv;
10423e308f20SDaniel P. Berrange
10433e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
10443e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block,
10457e60a6f5SMaxim Levitsky i,
10463e308f20SDaniel P. Berrange password,
10471ddd52e4SMaxim Levitsky masterkey,
10483e308f20SDaniel P. Berrange readfunc,
10493e308f20SDaniel P. Berrange opaque,
10503e308f20SDaniel P. Berrange errp);
10513e308f20SDaniel P. Berrange if (rv < 0) {
10523e308f20SDaniel P. Berrange goto error;
10533e308f20SDaniel P. Berrange }
10543e308f20SDaniel P. Berrange if (rv == 1) {
10553e308f20SDaniel P. Berrange return 0;
10563e308f20SDaniel P. Berrange }
10573e308f20SDaniel P. Berrange }
10583e308f20SDaniel P. Berrange
10593e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot");
10603e308f20SDaniel P. Berrange error:
10613e308f20SDaniel P. Berrange return -1;
10623e308f20SDaniel P. Berrange }
10633e308f20SDaniel P. Berrange
1064557d2bdcSMaxim Levitsky /*
1065557d2bdcSMaxim Levitsky * Returns true if a slot i is marked as active
1066557d2bdcSMaxim Levitsky * (contains encrypted copy of the master key)
1067557d2bdcSMaxim Levitsky */
1068557d2bdcSMaxim Levitsky static bool
qcrypto_block_luks_slot_active(const QCryptoBlockLUKS * luks,unsigned int slot_idx)1069557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks,
1070557d2bdcSMaxim Levitsky unsigned int slot_idx)
1071557d2bdcSMaxim Levitsky {
1072557d2bdcSMaxim Levitsky uint32_t val;
1073557d2bdcSMaxim Levitsky
1074557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
1075557d2bdcSMaxim Levitsky val = luks->header.key_slots[slot_idx].active;
1076557d2bdcSMaxim Levitsky return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
1077557d2bdcSMaxim Levitsky }
1078557d2bdcSMaxim Levitsky
1079557d2bdcSMaxim Levitsky /*
1080557d2bdcSMaxim Levitsky * Returns the number of slots that are marked as active
1081557d2bdcSMaxim Levitsky * (slots that contain encrypted copy of the master key)
1082557d2bdcSMaxim Levitsky */
1083557d2bdcSMaxim Levitsky static unsigned int
qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS * luks)1084557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks)
1085557d2bdcSMaxim Levitsky {
1086557d2bdcSMaxim Levitsky size_t i = 0;
1087557d2bdcSMaxim Levitsky unsigned int ret = 0;
1088557d2bdcSMaxim Levitsky
1089557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1090557d2bdcSMaxim Levitsky if (qcrypto_block_luks_slot_active(luks, i)) {
1091557d2bdcSMaxim Levitsky ret++;
1092557d2bdcSMaxim Levitsky }
1093557d2bdcSMaxim Levitsky }
1094557d2bdcSMaxim Levitsky return ret;
1095557d2bdcSMaxim Levitsky }
1096557d2bdcSMaxim Levitsky
1097557d2bdcSMaxim Levitsky /*
1098557d2bdcSMaxim Levitsky * Finds first key slot which is not active
1099557d2bdcSMaxim Levitsky * Returns the key slot index, or -1 if it doesn't exist
1100557d2bdcSMaxim Levitsky */
1101557d2bdcSMaxim Levitsky static int
qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS * luks)1102557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks)
1103557d2bdcSMaxim Levitsky {
1104557d2bdcSMaxim Levitsky size_t i;
1105557d2bdcSMaxim Levitsky
1106557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1107557d2bdcSMaxim Levitsky if (!qcrypto_block_luks_slot_active(luks, i)) {
1108557d2bdcSMaxim Levitsky return i;
1109557d2bdcSMaxim Levitsky }
1110557d2bdcSMaxim Levitsky }
1111557d2bdcSMaxim Levitsky return -1;
1112557d2bdcSMaxim Levitsky }
1113557d2bdcSMaxim Levitsky
1114557d2bdcSMaxim Levitsky /*
1115557d2bdcSMaxim Levitsky * Erases an keyslot given its index
1116557d2bdcSMaxim Levitsky * Returns:
1117557d2bdcSMaxim Levitsky * 0 if the keyslot was erased successfully
1118557d2bdcSMaxim Levitsky * -1 if a error occurred while erasing the keyslot
1119557d2bdcSMaxim Levitsky *
1120557d2bdcSMaxim Levitsky */
1121557d2bdcSMaxim Levitsky static int
qcrypto_block_luks_erase_key(QCryptoBlock * block,unsigned int slot_idx,QCryptoBlockWriteFunc writefunc,void * opaque,Error ** errp)1122557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block,
1123557d2bdcSMaxim Levitsky unsigned int slot_idx,
1124557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc,
1125557d2bdcSMaxim Levitsky void *opaque,
1126557d2bdcSMaxim Levitsky Error **errp)
1127557d2bdcSMaxim Levitsky {
1128557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque;
1129557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot;
1130557d2bdcSMaxim Levitsky g_autofree uint8_t *garbagesplitkey = NULL;
1131557d2bdcSMaxim Levitsky size_t splitkeylen;
1132557d2bdcSMaxim Levitsky size_t i;
1133557d2bdcSMaxim Levitsky Error *local_err = NULL;
1134557d2bdcSMaxim Levitsky int ret;
1135557d2bdcSMaxim Levitsky
1136557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
1137557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx];
1138557d2bdcSMaxim Levitsky
1139557d2bdcSMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes;
1140557d2bdcSMaxim Levitsky assert(splitkeylen > 0);
1141557d2bdcSMaxim Levitsky
1142557d2bdcSMaxim Levitsky garbagesplitkey = g_new0(uint8_t, splitkeylen);
1143557d2bdcSMaxim Levitsky
1144557d2bdcSMaxim Levitsky /* Reset the key slot header */
1145557d2bdcSMaxim Levitsky memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN);
1146557d2bdcSMaxim Levitsky slot->iterations = 0;
1147557d2bdcSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
1148557d2bdcSMaxim Levitsky
1149557d2bdcSMaxim Levitsky ret = qcrypto_block_luks_store_header(block, writefunc,
1150557d2bdcSMaxim Levitsky opaque, &local_err);
1151557d2bdcSMaxim Levitsky
1152557d2bdcSMaxim Levitsky if (ret < 0) {
1153557d2bdcSMaxim Levitsky error_propagate(errp, local_err);
1154557d2bdcSMaxim Levitsky }
1155557d2bdcSMaxim Levitsky /*
1156557d2bdcSMaxim Levitsky * Now try to erase the key material, even if the header
1157557d2bdcSMaxim Levitsky * update failed
1158557d2bdcSMaxim Levitsky */
1159557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) {
1160557d2bdcSMaxim Levitsky if (qcrypto_random_bytes(garbagesplitkey,
1161557d2bdcSMaxim Levitsky splitkeylen, &local_err) < 0) {
1162557d2bdcSMaxim Levitsky /*
1163557d2bdcSMaxim Levitsky * If we failed to get the random data, still write
1164557d2bdcSMaxim Levitsky * at least zeros to the key slot at least once
1165557d2bdcSMaxim Levitsky */
1166557d2bdcSMaxim Levitsky error_propagate(errp, local_err);
1167557d2bdcSMaxim Levitsky
1168557d2bdcSMaxim Levitsky if (i > 0) {
1169557d2bdcSMaxim Levitsky return -1;
1170557d2bdcSMaxim Levitsky }
1171557d2bdcSMaxim Levitsky }
1172557d2bdcSMaxim Levitsky if (writefunc(block,
1173557d2bdcSMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
1174557d2bdcSMaxim Levitsky garbagesplitkey,
1175557d2bdcSMaxim Levitsky splitkeylen,
1176557d2bdcSMaxim Levitsky opaque,
1177757dda54SAlberto Faria &local_err) < 0) {
1178557d2bdcSMaxim Levitsky error_propagate(errp, local_err);
1179557d2bdcSMaxim Levitsky return -1;
1180557d2bdcSMaxim Levitsky }
1181557d2bdcSMaxim Levitsky }
1182557d2bdcSMaxim Levitsky return ret;
1183557d2bdcSMaxim Levitsky }
11843e308f20SDaniel P. Berrange
11853e308f20SDaniel P. Berrange static int
qcrypto_block_luks_open(QCryptoBlock * block,QCryptoBlockOpenOptions * options,const char * optprefix,QCryptoBlockReadFunc readfunc,void * opaque,unsigned int flags,size_t n_threads,Error ** errp)11863e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block,
11873e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options,
11881cd9a787SDaniel P. Berrange const char *optprefix,
11893e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc,
11903e308f20SDaniel P. Berrange void *opaque,
11913e308f20SDaniel P. Berrange unsigned int flags,
1192c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads,
11933e308f20SDaniel P. Berrange Error **errp)
11943e308f20SDaniel P. Berrange {
11959d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL;
119657b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL;
119757b9f113SDaniel P. Berrangé g_autofree char *password = NULL;
11983e308f20SDaniel P. Berrange
11993e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
12003e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) {
12011cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher",
12021cd9a787SDaniel P. Berrange optprefix ? optprefix : "");
12033e308f20SDaniel P. Berrange return -1;
12043e308f20SDaniel P. Berrange }
12053e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(
12063e308f20SDaniel P. Berrange options->u.luks.key_secret, errp);
12073e308f20SDaniel P. Berrange if (!password) {
12083e308f20SDaniel P. Berrange return -1;
12093e308f20SDaniel P. Berrange }
12103e308f20SDaniel P. Berrange }
12113e308f20SDaniel P. Berrange
12123e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1);
12133e308f20SDaniel P. Berrange block->opaque = luks;
1214557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret);
12153e308f20SDaniel P. Berrange
1216dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) {
12173e308f20SDaniel P. Berrange goto fail;
12183e308f20SDaniel P. Berrange }
12193e308f20SDaniel P. Berrange
12209ad5c4e7SHyman Huang if (qcrypto_block_luks_check_header(luks, flags, errp) < 0) {
12213e308f20SDaniel P. Berrange goto fail;
12223e308f20SDaniel P. Berrange }
12233e308f20SDaniel P. Berrange
12249fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_parse_header(luks, errp) < 0) {
12253e308f20SDaniel P. Berrange goto fail;
12263e308f20SDaniel P. Berrange }
12273e308f20SDaniel P. Berrange
12283e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
12293e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for
12303e308f20SDaniel P. Berrange * and unlock the master key from that slot.
12313e308f20SDaniel P. Berrange */
12321ddd52e4SMaxim Levitsky
12331ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len);
12341ddd52e4SMaxim Levitsky
12353e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block,
12363e308f20SDaniel P. Berrange password,
12371ddd52e4SMaxim Levitsky masterkey,
12383e308f20SDaniel P. Berrange readfunc, opaque,
12393e308f20SDaniel P. Berrange errp) < 0) {
12403e308f20SDaniel P. Berrange goto fail;
12413e308f20SDaniel P. Berrange }
12423e308f20SDaniel P. Berrange
12433e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the
12443e308f20SDaniel P. Berrange * block device payload decryption objects
12453e308f20SDaniel P. Berrange */
12469d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg;
12479d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg,
12489d80e59dSMaxim Levitsky luks->cipher_mode);
12499d80e59dSMaxim Levitsky
12509d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
12519d80e59dSMaxim Levitsky luks->ivgen_cipher_alg,
12529d80e59dSMaxim Levitsky luks->ivgen_hash_alg,
12531ddd52e4SMaxim Levitsky masterkey,
12541ddd52e4SMaxim Levitsky luks->header.master_key_len,
12553e308f20SDaniel P. Berrange errp);
12563e308f20SDaniel P. Berrange if (!block->ivgen) {
12573e308f20SDaniel P. Berrange goto fail;
12583e308f20SDaniel P. Berrange }
12593e308f20SDaniel P. Berrange
126061dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block,
12619d80e59dSMaxim Levitsky luks->cipher_alg,
12629d80e59dSMaxim Levitsky luks->cipher_mode,
12631ddd52e4SMaxim Levitsky masterkey,
12641ddd52e4SMaxim Levitsky luks->header.master_key_len,
12651ddd52e4SMaxim Levitsky n_threads,
126661dd8a9aSMaxim Levitsky errp) < 0) {
12673e308f20SDaniel P. Berrange goto fail;
12683e308f20SDaniel P. Berrange }
12693e308f20SDaniel P. Berrange }
12703e308f20SDaniel P. Berrange
1271850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
1272f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector *
1273850f49deSDaniel P. Berrange block->sector_size;
1274*0bd779e2SHyman Huang block->detached_header = (block->payload_offset == 0) ? true : false;
12753e308f20SDaniel P. Berrange
12763e308f20SDaniel P. Berrange return 0;
12773e308f20SDaniel P. Berrange
12783e308f20SDaniel P. Berrange fail:
1279c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block);
12803e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen);
1281557d2bdcSMaxim Levitsky g_free(luks->secret);
12823e308f20SDaniel P. Berrange g_free(luks);
128361dd8a9aSMaxim Levitsky return -1;
12843e308f20SDaniel P. Berrange }
12853e308f20SDaniel P. Berrange
12863e308f20SDaniel P. Berrange
12872ef950f9SFam Zheng static void
qcrypto_block_luks_uuid_gen(uint8_t * uuidstr)12882ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
12893e308f20SDaniel P. Berrange {
12902ef950f9SFam Zheng QemuUUID uuid;
12912ef950f9SFam Zheng qemu_uuid_generate(&uuid);
12922ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr);
12933e308f20SDaniel P. Berrange }
12943e308f20SDaniel P. Berrange
12953e308f20SDaniel P. Berrange static int
qcrypto_block_luks_create(QCryptoBlock * block,QCryptoBlockCreateOptions * options,const char * optprefix,QCryptoBlockInitFunc initfunc,QCryptoBlockWriteFunc writefunc,void * opaque,Error ** errp)12963e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block,
12973e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options,
12981cd9a787SDaniel P. Berrange const char *optprefix,
12993e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc,
13003e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc,
13013e308f20SDaniel P. Berrange void *opaque,
13023e308f20SDaniel P. Berrange Error **errp)
13033e308f20SDaniel P. Berrange {
13043e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks;
13053e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts;
13063e308f20SDaniel P. Berrange Error *local_err = NULL;
130757b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL;
1308bd56a55aSMaxim Levitsky size_t header_sectors;
1309bd56a55aSMaxim Levitsky size_t split_key_sectors;
13103e308f20SDaniel P. Berrange size_t i;
131157b9f113SDaniel P. Berrangé g_autofree char *password = NULL;
13123e308f20SDaniel P. Berrange const char *cipher_alg;
13133e308f20SDaniel P. Berrange const char *cipher_mode;
13143e308f20SDaniel P. Berrange const char *ivgen_alg;
13153e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL;
13163e308f20SDaniel P. Berrange const char *hash_alg;
131757b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL;
131859b060beSDaniel P. Berrange uint64_t iters;
1319d74523a3SHyman Huang uint64_t detached_header_size;
13203e308f20SDaniel P. Berrange
13213e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
13223bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) {
1323557d2bdcSMaxim Levitsky luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
13243bd18890SDaniel P. Berrange }
13253e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) {
13263e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
13273e308f20SDaniel P. Berrange }
13283e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) {
13293e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS;
13303e308f20SDaniel P. Berrange }
13313e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) {
13323e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64;
13333e308f20SDaniel P. Berrange }
13343e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) {
13353e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256;
13363e308f20SDaniel P. Berrange }
13378b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
13388b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) {
13398b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256;
13408b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true;
13418b7cdba3SDaniel P. Berrange }
13428b7cdba3SDaniel P. Berrange }
13439d80e59dSMaxim Levitsky
13449d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1);
13459d80e59dSMaxim Levitsky block->opaque = luks;
13469d80e59dSMaxim Levitsky
13479d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg;
13489d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode;
13499d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg;
13509d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
13519d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg;
13529d80e59dSMaxim Levitsky
13539d80e59dSMaxim Levitsky
13548b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for
13558b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will
13568b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */
13573e308f20SDaniel P. Berrange
13583e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) {
13591cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher",
13601cd9a787SDaniel P. Berrange optprefix ? optprefix : "");
13619d80e59dSMaxim Levitsky goto error;
13623e308f20SDaniel P. Berrange }
1363557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret);
1364557d2bdcSMaxim Levitsky
13653e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
13663e308f20SDaniel P. Berrange if (!password) {
13679d80e59dSMaxim Levitsky goto error;
13683e308f20SDaniel P. Berrange }
13693e308f20SDaniel P. Berrange
13703e308f20SDaniel P. Berrange
13713e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic,
13723e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN);
13733e308f20SDaniel P. Berrange
13743e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and
13753e308f20SDaniel P. Berrange * then convert everything to big endian just before writing
13763e308f20SDaniel P. Berrange * it out to disk
13773e308f20SDaniel P. Berrange */
13783e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION;
13792ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid);
13803e308f20SDaniel P. Berrange
13813e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg,
13823e308f20SDaniel P. Berrange errp);
13833e308f20SDaniel P. Berrange if (!cipher_alg) {
13843e308f20SDaniel P. Berrange goto error;
13853e308f20SDaniel P. Berrange }
13863e308f20SDaniel P. Berrange
1387977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode);
1388977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg);
13893e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) {
1390977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg);
13913e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg,
13923e308f20SDaniel P. Berrange ivgen_hash_alg);
13933e308f20SDaniel P. Berrange } else {
13943e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg);
13953e308f20SDaniel P. Berrange }
1396977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg);
13973e308f20SDaniel P. Berrange
13983e308f20SDaniel P. Berrange
13993e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
14003e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header",
14013e308f20SDaniel P. Berrange cipher_alg);
14023e308f20SDaniel P. Berrange goto error;
14033e308f20SDaniel P. Berrange }
14043e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) {
14053e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header",
14063e308f20SDaniel P. Berrange cipher_mode_spec);
14073e308f20SDaniel P. Berrange goto error;
14083e308f20SDaniel P. Berrange }
14093e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) {
14103e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header",
14113e308f20SDaniel P. Berrange hash_alg);
14123e308f20SDaniel P. Berrange goto error;
14133e308f20SDaniel P. Berrange }
14143e308f20SDaniel P. Berrange
14153e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
14169d80e59dSMaxim Levitsky luks->ivgen_cipher_alg =
14179d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg,
14183e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg,
14193e308f20SDaniel P. Berrange &local_err);
14203e308f20SDaniel P. Berrange if (local_err) {
14213e308f20SDaniel P. Berrange error_propagate(errp, local_err);
14223e308f20SDaniel P. Berrange goto error;
14233e308f20SDaniel P. Berrange }
14243e308f20SDaniel P. Berrange } else {
14259d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg;
14263e308f20SDaniel P. Berrange }
14273e308f20SDaniel P. Berrange
14283e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg);
14293e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec);
14303e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg);
14313e308f20SDaniel P. Berrange
1432f0d3c362SMaxim Levitsky luks->header.master_key_len =
1433f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg);
1434f0d3c362SMaxim Levitsky
14353e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) {
1436f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2;
14373e308f20SDaniel P. Berrange }
14383e308f20SDaniel P. Berrange
14393e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key
14403e308f20SDaniel P. Berrange * with PBKDF later
14413e308f20SDaniel P. Berrange */
14423e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt,
14433e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN,
14443e308f20SDaniel P. Berrange errp) < 0) {
14453e308f20SDaniel P. Berrange goto error;
14463e308f20SDaniel P. Berrange }
14473e308f20SDaniel P. Berrange
14483e308f20SDaniel P. Berrange /* Generate random master key */
1449f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len);
14503e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey,
1451f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) {
14523e308f20SDaniel P. Berrange goto error;
14533e308f20SDaniel P. Berrange }
14543e308f20SDaniel P. Berrange
14553e308f20SDaniel P. Berrange
14563e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */
1457c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
1458c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey,
1459f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) {
14603e308f20SDaniel P. Berrange goto error;
14613e308f20SDaniel P. Berrange }
14623e308f20SDaniel P. Berrange
14633e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg;
14643e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg,
14653e308f20SDaniel P. Berrange luks_opts.cipher_mode);
14663e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg,
14679d80e59dSMaxim Levitsky luks->ivgen_cipher_alg,
14683e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg,
1469f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len,
14703e308f20SDaniel P. Berrange errp);
14713e308f20SDaniel P. Berrange
14723e308f20SDaniel P. Berrange if (!block->ivgen) {
14733e308f20SDaniel P. Berrange goto error;
14743e308f20SDaniel P. Berrange }
14753e308f20SDaniel P. Berrange
14763e308f20SDaniel P. Berrange
14773e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master
14783e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used
14793e308f20SDaniel P. Berrange */
148059b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
1481f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len,
14823e308f20SDaniel P. Berrange luks->header.master_key_salt,
14833e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN,
1484e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
14853e308f20SDaniel P. Berrange &local_err);
14863e308f20SDaniel P. Berrange if (local_err) {
14873e308f20SDaniel P. Berrange error_propagate(errp, local_err);
14883e308f20SDaniel P. Berrange goto error;
14893e308f20SDaniel P. Berrange }
14903e308f20SDaniel P. Berrange
14913bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) {
14923bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE,
14933bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale",
14943bd18890SDaniel P. Berrange (unsigned long long)iters);
14953bd18890SDaniel P. Berrange goto error;
14963bd18890SDaniel P. Berrange }
14973bd18890SDaniel P. Berrange
14983bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */
14993bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000;
15003bd18890SDaniel P. Berrange
15013e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no
15023e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that
15033e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second
15043e308f20SDaniel P. Berrange * in total time to check all keys */
150559b060beSDaniel P. Berrange iters /= 8;
150659b060beSDaniel P. Berrange if (iters > UINT32_MAX) {
150759b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE,
150859b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u",
150959b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX);
151059b060beSDaniel P. Berrange goto error;
151159b060beSDaniel P. Berrange }
151259b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS);
151359b060beSDaniel P. Berrange luks->header.master_key_iterations = iters;
15143e308f20SDaniel P. Berrange
15153e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS
15163e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted
15173e308f20SDaniel P. Berrange * device to verify that the user password unlocked a
15183e308f20SDaniel P. Berrange * valid master key
15193e308f20SDaniel P. Berrange */
15203e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg,
1521f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len,
15223e308f20SDaniel P. Berrange luks->header.master_key_salt,
15233e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN,
15243e308f20SDaniel P. Berrange luks->header.master_key_iterations,
15253e308f20SDaniel P. Berrange luks->header.master_key_digest,
15263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
15273e308f20SDaniel P. Berrange errp) < 0) {
15283e308f20SDaniel P. Berrange goto error;
15293e308f20SDaniel P. Berrange }
15303e308f20SDaniel P. Berrange
1531bd56a55aSMaxim Levitsky /* start with the sector that follows the header*/
1532bd56a55aSMaxim Levitsky header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
1533bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
15343e308f20SDaniel P. Berrange
1535bd56a55aSMaxim Levitsky split_key_sectors =
1536bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks,
1537bd56a55aSMaxim Levitsky header_sectors,
1538bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_STRIPES);
1539bd56a55aSMaxim Levitsky
15403e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1541bd56a55aSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i];
1542bd56a55aSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
15433e308f20SDaniel P. Berrange
1544bd56a55aSMaxim Levitsky slot->key_offset_sector = header_sectors + i * split_key_sectors;
1545bd56a55aSMaxim Levitsky slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
15463e308f20SDaniel P. Berrange }
15473e308f20SDaniel P. Berrange
1548d74523a3SHyman Huang if (block->detached_header) {
1549d74523a3SHyman Huang /*
1550d74523a3SHyman Huang * For a detached LUKS header image, set the payload_offset_sector
1551d74523a3SHyman Huang * to 0 to specify the starting point for read/write
1552d74523a3SHyman Huang */
1553d74523a3SHyman Huang luks->header.payload_offset_sector = 0;
1554d74523a3SHyman Huang } else {
1555d74523a3SHyman Huang /*
1556d74523a3SHyman Huang * The total size of the LUKS headers is the partition header + key
15573e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with
15583e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up
1559d74523a3SHyman Huang * to the nearest sector
1560d74523a3SHyman Huang */
1561bd56a55aSMaxim Levitsky luks->header.payload_offset_sector = header_sectors +
1562bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
1563d74523a3SHyman Huang }
15643e308f20SDaniel P. Berrange
1565850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
1566f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector *
1567850f49deSDaniel P. Berrange block->sector_size;
1568d74523a3SHyman Huang detached_header_size =
1569d74523a3SHyman Huang (header_sectors + QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS *
1570d74523a3SHyman Huang split_key_sectors) * block->sector_size;
15713e308f20SDaniel P. Berrange
15723e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */
1573d74523a3SHyman Huang initfunc(block, detached_header_size, opaque, &local_err);
15743e308f20SDaniel P. Berrange if (local_err) {
15753e308f20SDaniel P. Berrange error_propagate(errp, local_err);
15763e308f20SDaniel P. Berrange goto error;
15773e308f20SDaniel P. Berrange }
15783e308f20SDaniel P. Berrange
15793e308f20SDaniel P. Berrange
15803994a7c9SMaxim Levitsky /* populate the slot 0 with the password encrypted master key*/
15813994a7c9SMaxim Levitsky /* This will also store the header */
15823994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_key(block,
15833994a7c9SMaxim Levitsky 0,
15843994a7c9SMaxim Levitsky password,
15853994a7c9SMaxim Levitsky masterkey,
15863994a7c9SMaxim Levitsky luks_opts.iter_time,
15873994a7c9SMaxim Levitsky writefunc,
1588e4a3507eSDaniel P. Berrange opaque,
15893994a7c9SMaxim Levitsky errp) < 0) {
15903e308f20SDaniel P. Berrange goto error;
15913e308f20SDaniel P. Berrange }
15923e308f20SDaniel P. Berrange
1593f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len);
15943e308f20SDaniel P. Berrange
15953e308f20SDaniel P. Berrange return 0;
15963e308f20SDaniel P. Berrange
15973e308f20SDaniel P. Berrange error:
15983e308f20SDaniel P. Berrange if (masterkey) {
1599f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len);
16003e308f20SDaniel P. Berrange }
16013e308f20SDaniel P. Berrange
1602c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block);
1603b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen);
1604b640adcaSVladimir Sementsov-Ogievskiy
1605557d2bdcSMaxim Levitsky g_free(luks->secret);
16063e308f20SDaniel P. Berrange g_free(luks);
16073e308f20SDaniel P. Berrange return -1;
16083e308f20SDaniel P. Berrange }
16093e308f20SDaniel P. Berrange
1610557d2bdcSMaxim Levitsky static int
qcrypto_block_luks_amend_add_keyslot(QCryptoBlock * block,QCryptoBlockReadFunc readfunc,QCryptoBlockWriteFunc writefunc,void * opaque,QCryptoBlockAmendOptionsLUKS * opts_luks,bool force,Error ** errp)1611557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block,
1612557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc,
1613557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc,
1614557d2bdcSMaxim Levitsky void *opaque,
1615557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks,
1616557d2bdcSMaxim Levitsky bool force,
1617557d2bdcSMaxim Levitsky Error **errp)
1618557d2bdcSMaxim Levitsky {
1619557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque;
1620557d2bdcSMaxim Levitsky uint64_t iter_time = opts_luks->has_iter_time ?
1621557d2bdcSMaxim Levitsky opts_luks->iter_time :
1622557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
1623557d2bdcSMaxim Levitsky int keyslot;
1624557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL;
1625557d2bdcSMaxim Levitsky g_autofree char *new_password = NULL;
1626557d2bdcSMaxim Levitsky g_autofree uint8_t *master_key = NULL;
1627557d2bdcSMaxim Levitsky
162816110c8bSMarkus Armbruster char *secret = opts_luks->secret ?: luks->secret;
1629557d2bdcSMaxim Levitsky
163016110c8bSMarkus Armbruster if (!opts_luks->new_secret) {
1631557d2bdcSMaxim Levitsky error_setg(errp, "'new-secret' is required to activate a keyslot");
1632557d2bdcSMaxim Levitsky return -1;
1633557d2bdcSMaxim Levitsky }
163416110c8bSMarkus Armbruster if (opts_luks->old_secret) {
1635557d2bdcSMaxim Levitsky error_setg(errp,
1636557d2bdcSMaxim Levitsky "'old-secret' must not be given when activating keyslots");
1637557d2bdcSMaxim Levitsky return -1;
1638557d2bdcSMaxim Levitsky }
1639557d2bdcSMaxim Levitsky
1640557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) {
1641557d2bdcSMaxim Levitsky keyslot = opts_luks->keyslot;
1642557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
1643557d2bdcSMaxim Levitsky error_setg(errp,
1644557d2bdcSMaxim Levitsky "Invalid keyslot %u specified, must be between 0 and %u",
1645557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
1646557d2bdcSMaxim Levitsky return -1;
1647557d2bdcSMaxim Levitsky }
1648557d2bdcSMaxim Levitsky } else {
1649557d2bdcSMaxim Levitsky keyslot = qcrypto_block_luks_find_free_keyslot(luks);
1650557d2bdcSMaxim Levitsky if (keyslot == -1) {
1651557d2bdcSMaxim Levitsky error_setg(errp,
1652557d2bdcSMaxim Levitsky "Can't add a keyslot - all keyslots are in use");
1653557d2bdcSMaxim Levitsky return -1;
1654557d2bdcSMaxim Levitsky }
1655557d2bdcSMaxim Levitsky }
1656557d2bdcSMaxim Levitsky
1657557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) {
1658557d2bdcSMaxim Levitsky error_setg(errp,
1659557d2bdcSMaxim Levitsky "Refusing to overwrite active keyslot %i - "
1660557d2bdcSMaxim Levitsky "please erase it first",
1661557d2bdcSMaxim Levitsky keyslot);
1662557d2bdcSMaxim Levitsky return -1;
1663557d2bdcSMaxim Levitsky }
1664557d2bdcSMaxim Levitsky
1665557d2bdcSMaxim Levitsky /* Locate the password that will be used to retrieve the master key */
1666557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(secret, errp);
1667557d2bdcSMaxim Levitsky if (!old_password) {
1668557d2bdcSMaxim Levitsky return -1;
1669557d2bdcSMaxim Levitsky }
1670557d2bdcSMaxim Levitsky
1671557d2bdcSMaxim Levitsky /* Retrieve the master key */
1672557d2bdcSMaxim Levitsky master_key = g_new0(uint8_t, luks->header.master_key_len);
1673557d2bdcSMaxim Levitsky
1674557d2bdcSMaxim Levitsky if (qcrypto_block_luks_find_key(block, old_password, master_key,
1675557d2bdcSMaxim Levitsky readfunc, opaque, errp) < 0) {
1676557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to retrieve the master key");
1677557d2bdcSMaxim Levitsky return -1;
1678557d2bdcSMaxim Levitsky }
1679557d2bdcSMaxim Levitsky
1680557d2bdcSMaxim Levitsky /* Locate the new password*/
1681557d2bdcSMaxim Levitsky new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp);
1682557d2bdcSMaxim Levitsky if (!new_password) {
1683557d2bdcSMaxim Levitsky return -1;
1684557d2bdcSMaxim Levitsky }
1685557d2bdcSMaxim Levitsky
1686557d2bdcSMaxim Levitsky /* Now set the new keyslots */
1687557d2bdcSMaxim Levitsky if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key,
1688557d2bdcSMaxim Levitsky iter_time, writefunc, opaque, errp)) {
1689557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to write to keyslot %i", keyslot);
1690557d2bdcSMaxim Levitsky return -1;
1691557d2bdcSMaxim Levitsky }
1692557d2bdcSMaxim Levitsky return 0;
1693557d2bdcSMaxim Levitsky }
1694557d2bdcSMaxim Levitsky
1695557d2bdcSMaxim Levitsky static int
qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock * block,QCryptoBlockReadFunc readfunc,QCryptoBlockWriteFunc writefunc,void * opaque,QCryptoBlockAmendOptionsLUKS * opts_luks,bool force,Error ** errp)1696557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block,
1697557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc,
1698557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc,
1699557d2bdcSMaxim Levitsky void *opaque,
1700557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks,
1701557d2bdcSMaxim Levitsky bool force,
1702557d2bdcSMaxim Levitsky Error **errp)
1703557d2bdcSMaxim Levitsky {
1704557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque;
1705557d2bdcSMaxim Levitsky g_autofree uint8_t *tmpkey = NULL;
1706557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL;
1707557d2bdcSMaxim Levitsky
170816110c8bSMarkus Armbruster if (opts_luks->new_secret) {
1709557d2bdcSMaxim Levitsky error_setg(errp,
1710557d2bdcSMaxim Levitsky "'new-secret' must not be given when erasing keyslots");
1711557d2bdcSMaxim Levitsky return -1;
1712557d2bdcSMaxim Levitsky }
1713557d2bdcSMaxim Levitsky if (opts_luks->has_iter_time) {
1714557d2bdcSMaxim Levitsky error_setg(errp,
1715557d2bdcSMaxim Levitsky "'iter-time' must not be given when erasing keyslots");
1716557d2bdcSMaxim Levitsky return -1;
1717557d2bdcSMaxim Levitsky }
171816110c8bSMarkus Armbruster if (opts_luks->secret) {
1719557d2bdcSMaxim Levitsky error_setg(errp,
1720557d2bdcSMaxim Levitsky "'secret' must not be given when erasing keyslots");
1721557d2bdcSMaxim Levitsky return -1;
1722557d2bdcSMaxim Levitsky }
1723557d2bdcSMaxim Levitsky
1724557d2bdcSMaxim Levitsky /* Load the old password if given */
172516110c8bSMarkus Armbruster if (opts_luks->old_secret) {
1726557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret,
1727557d2bdcSMaxim Levitsky errp);
1728557d2bdcSMaxim Levitsky if (!old_password) {
1729557d2bdcSMaxim Levitsky return -1;
1730557d2bdcSMaxim Levitsky }
1731557d2bdcSMaxim Levitsky
1732557d2bdcSMaxim Levitsky /*
1733557d2bdcSMaxim Levitsky * Allocate a temporary key buffer that we will need when
1734557d2bdcSMaxim Levitsky * checking if slot matches the given old password
1735557d2bdcSMaxim Levitsky */
1736557d2bdcSMaxim Levitsky tmpkey = g_new0(uint8_t, luks->header.master_key_len);
1737557d2bdcSMaxim Levitsky }
1738557d2bdcSMaxim Levitsky
1739557d2bdcSMaxim Levitsky /* Erase an explicitly given keyslot */
1740557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) {
1741557d2bdcSMaxim Levitsky int keyslot = opts_luks->keyslot;
1742557d2bdcSMaxim Levitsky
1743557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
1744557d2bdcSMaxim Levitsky error_setg(errp,
1745557d2bdcSMaxim Levitsky "Invalid keyslot %i specified, must be between 0 and %i",
1746557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
1747557d2bdcSMaxim Levitsky return -1;
1748557d2bdcSMaxim Levitsky }
1749557d2bdcSMaxim Levitsky
175016110c8bSMarkus Armbruster if (opts_luks->old_secret) {
1751557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block,
1752557d2bdcSMaxim Levitsky keyslot,
1753557d2bdcSMaxim Levitsky old_password,
1754557d2bdcSMaxim Levitsky tmpkey,
1755557d2bdcSMaxim Levitsky readfunc,
1756557d2bdcSMaxim Levitsky opaque,
1757557d2bdcSMaxim Levitsky errp);
1758557d2bdcSMaxim Levitsky if (rv == -1) {
1759557d2bdcSMaxim Levitsky return -1;
1760557d2bdcSMaxim Levitsky } else if (rv == 0) {
1761557d2bdcSMaxim Levitsky error_setg(errp,
1762557d2bdcSMaxim Levitsky "Given keyslot %i doesn't contain the given "
1763557d2bdcSMaxim Levitsky "old password for erase operation",
1764557d2bdcSMaxim Levitsky keyslot);
1765557d2bdcSMaxim Levitsky return -1;
1766557d2bdcSMaxim Levitsky }
1767557d2bdcSMaxim Levitsky }
1768557d2bdcSMaxim Levitsky
1769557d2bdcSMaxim Levitsky if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) {
1770557d2bdcSMaxim Levitsky error_setg(errp,
1771557d2bdcSMaxim Levitsky "Given keyslot %i is already erased (inactive) ",
1772557d2bdcSMaxim Levitsky keyslot);
1773557d2bdcSMaxim Levitsky return -1;
1774557d2bdcSMaxim Levitsky }
1775557d2bdcSMaxim Levitsky
1776557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) {
1777557d2bdcSMaxim Levitsky error_setg(errp,
1778557d2bdcSMaxim Levitsky "Attempt to erase the only active keyslot %i "
1779557d2bdcSMaxim Levitsky "which will erase all the data in the image "
1780557d2bdcSMaxim Levitsky "irreversibly - refusing operation",
1781557d2bdcSMaxim Levitsky keyslot);
1782557d2bdcSMaxim Levitsky return -1;
1783557d2bdcSMaxim Levitsky }
1784557d2bdcSMaxim Levitsky
1785557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, keyslot,
1786557d2bdcSMaxim Levitsky writefunc, opaque, errp)) {
1787557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %i", keyslot);
1788557d2bdcSMaxim Levitsky return -1;
1789557d2bdcSMaxim Levitsky }
1790557d2bdcSMaxim Levitsky
1791557d2bdcSMaxim Levitsky /* Erase all keyslots that match the given old password */
179216110c8bSMarkus Armbruster } else if (opts_luks->old_secret) {
1793557d2bdcSMaxim Levitsky
1794557d2bdcSMaxim Levitsky unsigned long slots_to_erase_bitmap = 0;
1795557d2bdcSMaxim Levitsky size_t i;
1796557d2bdcSMaxim Levitsky int slot_count;
1797557d2bdcSMaxim Levitsky
1798557d2bdcSMaxim Levitsky assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <=
1799557d2bdcSMaxim Levitsky sizeof(slots_to_erase_bitmap) * 8);
1800557d2bdcSMaxim Levitsky
1801557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1802557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block,
1803557d2bdcSMaxim Levitsky i,
1804557d2bdcSMaxim Levitsky old_password,
1805557d2bdcSMaxim Levitsky tmpkey,
1806557d2bdcSMaxim Levitsky readfunc,
1807557d2bdcSMaxim Levitsky opaque,
1808557d2bdcSMaxim Levitsky errp);
1809557d2bdcSMaxim Levitsky if (rv == -1) {
1810557d2bdcSMaxim Levitsky return -1;
1811557d2bdcSMaxim Levitsky } else if (rv == 1) {
1812557d2bdcSMaxim Levitsky bitmap_set(&slots_to_erase_bitmap, i, 1);
1813557d2bdcSMaxim Levitsky }
1814557d2bdcSMaxim Levitsky }
1815557d2bdcSMaxim Levitsky
1816557d2bdcSMaxim Levitsky slot_count = bitmap_count_one(&slots_to_erase_bitmap,
1817557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
1818557d2bdcSMaxim Levitsky if (slot_count == 0) {
1819557d2bdcSMaxim Levitsky error_setg(errp,
1820557d2bdcSMaxim Levitsky "No keyslots match given (old) password for erase operation");
1821557d2bdcSMaxim Levitsky return -1;
1822557d2bdcSMaxim Levitsky }
1823557d2bdcSMaxim Levitsky
1824557d2bdcSMaxim Levitsky if (!force &&
1825557d2bdcSMaxim Levitsky slot_count == qcrypto_block_luks_count_active_slots(luks)) {
1826557d2bdcSMaxim Levitsky error_setg(errp,
1827557d2bdcSMaxim Levitsky "All the active keyslots match the (old) password that "
1828557d2bdcSMaxim Levitsky "was given and erasing them will erase all the data in "
1829557d2bdcSMaxim Levitsky "the image irreversibly - refusing operation");
1830557d2bdcSMaxim Levitsky return -1;
1831557d2bdcSMaxim Levitsky }
1832557d2bdcSMaxim Levitsky
1833557d2bdcSMaxim Levitsky /* Now apply the update */
1834557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1835557d2bdcSMaxim Levitsky if (!test_bit(i, &slots_to_erase_bitmap)) {
1836557d2bdcSMaxim Levitsky continue;
1837557d2bdcSMaxim Levitsky }
1838557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, i, writefunc,
1839557d2bdcSMaxim Levitsky opaque, errp)) {
1840557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %zu", i);
1841557d2bdcSMaxim Levitsky return -1;
1842557d2bdcSMaxim Levitsky }
1843557d2bdcSMaxim Levitsky }
1844557d2bdcSMaxim Levitsky } else {
1845557d2bdcSMaxim Levitsky error_setg(errp,
1846557d2bdcSMaxim Levitsky "To erase keyslot(s), either explicit keyslot index "
1847557d2bdcSMaxim Levitsky "or the password currently contained in them must be given");
1848557d2bdcSMaxim Levitsky return -1;
1849557d2bdcSMaxim Levitsky }
1850557d2bdcSMaxim Levitsky return 0;
1851557d2bdcSMaxim Levitsky }
1852557d2bdcSMaxim Levitsky
1853557d2bdcSMaxim Levitsky static int
qcrypto_block_luks_amend_options(QCryptoBlock * block,QCryptoBlockReadFunc readfunc,QCryptoBlockWriteFunc writefunc,void * opaque,QCryptoBlockAmendOptions * options,bool force,Error ** errp)1854557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block,
1855557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc,
1856557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc,
1857557d2bdcSMaxim Levitsky void *opaque,
1858557d2bdcSMaxim Levitsky QCryptoBlockAmendOptions *options,
1859557d2bdcSMaxim Levitsky bool force,
1860557d2bdcSMaxim Levitsky Error **errp)
1861557d2bdcSMaxim Levitsky {
1862557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks;
1863557d2bdcSMaxim Levitsky
1864557d2bdcSMaxim Levitsky switch (opts_luks->state) {
1865557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE:
1866557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_add_keyslot(block, readfunc,
1867557d2bdcSMaxim Levitsky writefunc, opaque,
1868557d2bdcSMaxim Levitsky opts_luks, force, errp);
1869557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE:
1870557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_erase_keyslots(block, readfunc,
1871557d2bdcSMaxim Levitsky writefunc, opaque,
1872557d2bdcSMaxim Levitsky opts_luks, force, errp);
1873557d2bdcSMaxim Levitsky default:
1874557d2bdcSMaxim Levitsky g_assert_not_reached();
1875557d2bdcSMaxim Levitsky }
1876557d2bdcSMaxim Levitsky }
18773e308f20SDaniel P. Berrange
qcrypto_block_luks_get_info(QCryptoBlock * block,QCryptoBlockInfo * info,Error ** errp)187840c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block,
187940c85028SDaniel P. Berrange QCryptoBlockInfo *info,
188040c85028SDaniel P. Berrange Error **errp)
188140c85028SDaniel P. Berrange {
188240c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque;
188340c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot;
1884c3033fd3SEric Blake QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots;
188540c85028SDaniel P. Berrange size_t i;
188640c85028SDaniel P. Berrange
188740c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg;
188840c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode;
188940c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg;
189040c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
189140c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true;
189240c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg;
189340c85028SDaniel P. Berrange }
189440c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg;
189540c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset;
189640c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations;
189740c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid,
189840c85028SDaniel P. Berrange sizeof(luks->header.uuid));
1899*0bd779e2SHyman Huang info->u.luks.detached_header = block->detached_header;
190040c85028SDaniel P. Berrange
190140c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
1902c3033fd3SEric Blake slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
190340c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active ==
190440c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
1905f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector
190640c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
190740c85028SDaniel P. Berrange if (slot->active) {
190840c85028SDaniel P. Berrange slot->has_iters = true;
190940c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations;
191040c85028SDaniel P. Berrange slot->has_stripes = true;
191140c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes;
191240c85028SDaniel P. Berrange }
191340c85028SDaniel P. Berrange
1914c3033fd3SEric Blake QAPI_LIST_APPEND(tail, slot);
191540c85028SDaniel P. Berrange }
191640c85028SDaniel P. Berrange
191740c85028SDaniel P. Berrange return 0;
191840c85028SDaniel P. Berrange }
191940c85028SDaniel P. Berrange
192040c85028SDaniel P. Berrange
qcrypto_block_luks_cleanup(QCryptoBlock * block)19213e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
19223e308f20SDaniel P. Berrange {
1923557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque;
1924557d2bdcSMaxim Levitsky if (luks) {
1925557d2bdcSMaxim Levitsky g_free(luks->secret);
1926557d2bdcSMaxim Levitsky g_free(luks);
1927557d2bdcSMaxim Levitsky }
19283e308f20SDaniel P. Berrange }
19293e308f20SDaniel P. Berrange
19303e308f20SDaniel P. Berrange
19313e308f20SDaniel P. Berrange static int
qcrypto_block_luks_decrypt(QCryptoBlock * block,uint64_t offset,uint8_t * buf,size_t len,Error ** errp)19323e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block,
19334609742aSDaniel P. Berrange uint64_t offset,
19343e308f20SDaniel P. Berrange uint8_t *buf,
19353e308f20SDaniel P. Berrange size_t len,
19363e308f20SDaniel P. Berrange Error **errp)
19373e308f20SDaniel P. Berrange {
19384609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19394609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19400f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block,
19413e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
19424609742aSDaniel P. Berrange offset, buf, len, errp);
19433e308f20SDaniel P. Berrange }
19443e308f20SDaniel P. Berrange
19453e308f20SDaniel P. Berrange
19463e308f20SDaniel P. Berrange static int
qcrypto_block_luks_encrypt(QCryptoBlock * block,uint64_t offset,uint8_t * buf,size_t len,Error ** errp)19473e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block,
19484609742aSDaniel P. Berrange uint64_t offset,
19493e308f20SDaniel P. Berrange uint8_t *buf,
19503e308f20SDaniel P. Berrange size_t len,
19513e308f20SDaniel P. Berrange Error **errp)
19523e308f20SDaniel P. Berrange {
19534609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19544609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE));
19550f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block,
19563e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
19574609742aSDaniel P. Berrange offset, buf, len, errp);
19583e308f20SDaniel P. Berrange }
19593e308f20SDaniel P. Berrange
19603e308f20SDaniel P. Berrange
19613e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = {
19623e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open,
19633e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create,
1964557d2bdcSMaxim Levitsky .amend = qcrypto_block_luks_amend_options,
196540c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info,
19663e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup,
19673e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt,
19683e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt,
19693e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format,
19703e308f20SDaniel P. Berrange };
1971