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 98*52ed9f45SHyman Huang #ifdef CONFIG_CRYPTO_SM4 99*52ed9f45SHyman Huang static const QCryptoBlockLUKSCipherSizeMap 100*52ed9f45SHyman Huang qcrypto_block_luks_cipher_size_map_sm4[] = { 101*52ed9f45SHyman Huang { 16, QCRYPTO_CIPHER_ALG_SM4}, 102*52ed9f45SHyman Huang { 0, 0 }, 103*52ed9f45SHyman Huang }; 104*52ed9f45SHyman Huang #endif 105*52ed9f45SHyman 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 }, 112*52ed9f45SHyman Huang #ifdef CONFIG_CRYPTO_SM4 113*52ed9f45SHyman Huang { "sm4", qcrypto_block_luks_cipher_size_map_sm4}, 114*52ed9f45SHyman 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 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 * 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 */ 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 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 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 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 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 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 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 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 4719fa9c1c2SMaxim Levitsky qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp) 4729fa9c1c2SMaxim Levitsky { 473befdba9eSMaxim Levitsky size_t i, j; 474befdba9eSMaxim Levitsky 475befdba9eSMaxim Levitsky unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 476befdba9eSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 477befdba9eSMaxim Levitsky 4789fa9c1c2SMaxim Levitsky if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 4799fa9c1c2SMaxim Levitsky QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 4809fa9c1c2SMaxim Levitsky error_setg(errp, "Volume is not in LUKS format"); 4819fa9c1c2SMaxim Levitsky return -1; 4829fa9c1c2SMaxim Levitsky } 4839fa9c1c2SMaxim Levitsky 4849fa9c1c2SMaxim Levitsky if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 4859fa9c1c2SMaxim Levitsky error_setg(errp, "LUKS version %" PRIu32 " is not supported", 4869fa9c1c2SMaxim Levitsky luks->header.version); 4879fa9c1c2SMaxim Levitsky return -1; 4889fa9c1c2SMaxim Levitsky } 489befdba9eSMaxim Levitsky 490c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_name, '\0', 491c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_name))) { 492c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher name is not NUL terminated"); 493c1d8634cSDaniel P. Berrangé return -1; 494c1d8634cSDaniel P. Berrangé } 495c1d8634cSDaniel P. Berrangé 496c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_mode, '\0', 497c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_mode))) { 498c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher mode is not NUL terminated"); 499c1d8634cSDaniel P. Berrangé return -1; 500c1d8634cSDaniel P. Berrangé } 501c1d8634cSDaniel P. Berrangé 502c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.hash_spec, '\0', 503c1d8634cSDaniel P. Berrangé sizeof(luks->header.hash_spec))) { 504c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header hash spec is not NUL terminated"); 505c1d8634cSDaniel P. Berrangé return -1; 506c1d8634cSDaniel P. Berrangé } 507c1d8634cSDaniel P. Berrangé 508d233fbc3SDaniel P. Berrangé if (luks->header.payload_offset_sector < 509d233fbc3SDaniel P. Berrangé DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 510d233fbc3SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 511d233fbc3SDaniel P. Berrangé error_setg(errp, "LUKS payload is overlapping with the header"); 512d233fbc3SDaniel P. Berrangé return -1; 513d233fbc3SDaniel P. Berrangé } 514d233fbc3SDaniel P. Berrangé 515b57151acSDaniel P. Berrangé if (luks->header.master_key_iterations == 0) { 516b57151acSDaniel P. Berrangé error_setg(errp, "LUKS key iteration count is zero"); 517b57151acSDaniel P. Berrangé return -1; 518b57151acSDaniel P. Berrangé } 519b57151acSDaniel P. Berrangé 520befdba9eSMaxim Levitsky /* Check all keyslots for corruption */ 521befdba9eSMaxim Levitsky for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) { 522befdba9eSMaxim Levitsky 523befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i]; 524befdba9eSMaxim Levitsky unsigned int start1 = slot1->key_offset_sector; 525befdba9eSMaxim Levitsky unsigned int len1 = 526befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 527befdba9eSMaxim Levitsky header_sectors, 528befdba9eSMaxim Levitsky slot1->stripes); 529befdba9eSMaxim Levitsky 530f1195961SDaniel P. Berrangé if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) { 531f1195961SDaniel P. Berrangé error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)", 532f1195961SDaniel P. Berrangé i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES); 533befdba9eSMaxim Levitsky return -1; 534befdba9eSMaxim Levitsky } 535befdba9eSMaxim Levitsky 536befdba9eSMaxim Levitsky if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED && 537befdba9eSMaxim Levitsky slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 538befdba9eSMaxim Levitsky error_setg(errp, 539befdba9eSMaxim Levitsky "Keyslot %zu state (active/disable) is corrupted", i); 540befdba9eSMaxim Levitsky return -1; 541befdba9eSMaxim Levitsky } 542befdba9eSMaxim Levitsky 543b57151acSDaniel P. Berrangé if (slot1->active == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED && 544b57151acSDaniel P. Berrangé slot1->iterations == 0) { 545b57151acSDaniel P. Berrangé error_setg(errp, "Keyslot %zu iteration count is zero", i); 546b57151acSDaniel P. Berrangé return -1; 547b57151acSDaniel P. Berrangé } 548b57151acSDaniel P. Berrangé 549c5f69628SDaniel P. Berrangé if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 55093569c37SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 55193569c37SDaniel P. Berrangé error_setg(errp, 55293569c37SDaniel P. Berrangé "Keyslot %zu is overlapping with the LUKS header", 55393569c37SDaniel P. Berrangé i); 55493569c37SDaniel P. Berrangé return -1; 55593569c37SDaniel P. Berrangé } 55693569c37SDaniel P. Berrangé 557befdba9eSMaxim Levitsky if (start1 + len1 > luks->header.payload_offset_sector) { 558befdba9eSMaxim Levitsky error_setg(errp, 559befdba9eSMaxim Levitsky "Keyslot %zu is overlapping with the encrypted payload", 560befdba9eSMaxim Levitsky i); 561befdba9eSMaxim Levitsky return -1; 562befdba9eSMaxim Levitsky } 563befdba9eSMaxim Levitsky 564befdba9eSMaxim Levitsky for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) { 565befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j]; 566befdba9eSMaxim Levitsky unsigned int start2 = slot2->key_offset_sector; 567befdba9eSMaxim Levitsky unsigned int len2 = 568befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 569befdba9eSMaxim Levitsky header_sectors, 570befdba9eSMaxim Levitsky slot2->stripes); 571befdba9eSMaxim Levitsky 572befdba9eSMaxim Levitsky if (start1 + len1 > start2 && start2 + len2 > start1) { 573befdba9eSMaxim Levitsky error_setg(errp, 574befdba9eSMaxim Levitsky "Keyslots %zu and %zu are overlapping in the header", 575befdba9eSMaxim Levitsky i, j); 576befdba9eSMaxim Levitsky return -1; 577befdba9eSMaxim Levitsky } 578befdba9eSMaxim Levitsky } 579befdba9eSMaxim Levitsky 580befdba9eSMaxim Levitsky } 5819fa9c1c2SMaxim Levitsky return 0; 5829fa9c1c2SMaxim Levitsky } 5839fa9c1c2SMaxim Levitsky 5849fa9c1c2SMaxim Levitsky /* 5859fa9c1c2SMaxim Levitsky * Parses the crypto parameters that are stored in the LUKS header 5869fa9c1c2SMaxim Levitsky */ 5879fa9c1c2SMaxim Levitsky 5889fa9c1c2SMaxim Levitsky static int 5899fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp) 5909fa9c1c2SMaxim Levitsky { 5919fa9c1c2SMaxim Levitsky g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode); 5929fa9c1c2SMaxim Levitsky char *ivgen_name, *ivhash_name; 5939fa9c1c2SMaxim Levitsky Error *local_err = NULL; 5949fa9c1c2SMaxim Levitsky 5959fa9c1c2SMaxim Levitsky /* 5969fa9c1c2SMaxim Levitsky * The cipher_mode header contains a string that we have 5979fa9c1c2SMaxim Levitsky * to further parse, of the format 5989fa9c1c2SMaxim Levitsky * 5999fa9c1c2SMaxim Levitsky * <cipher-mode>-<iv-generator>[:<iv-hash>] 6009fa9c1c2SMaxim Levitsky * 6019fa9c1c2SMaxim Levitsky * eg cbc-essiv:sha256, cbc-plain64 6029fa9c1c2SMaxim Levitsky */ 6039fa9c1c2SMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 6049fa9c1c2SMaxim Levitsky if (!ivgen_name) { 6056c198932SDaniel P. Berrangé error_setg(errp, "Unexpected cipher mode string format '%s'", 6069fa9c1c2SMaxim Levitsky luks->header.cipher_mode); 6079fa9c1c2SMaxim Levitsky return -1; 6089fa9c1c2SMaxim Levitsky } 6099fa9c1c2SMaxim Levitsky *ivgen_name = '\0'; 6109fa9c1c2SMaxim Levitsky ivgen_name++; 6119fa9c1c2SMaxim Levitsky 6129fa9c1c2SMaxim Levitsky ivhash_name = strchr(ivgen_name, ':'); 6139fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6149fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = 0; 6159fa9c1c2SMaxim Levitsky } else { 6169fa9c1c2SMaxim Levitsky *ivhash_name = '\0'; 6179fa9c1c2SMaxim Levitsky ivhash_name++; 6189fa9c1c2SMaxim Levitsky 6199fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 6209fa9c1c2SMaxim Levitsky &local_err); 6219fa9c1c2SMaxim Levitsky if (local_err) { 6229fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6239fa9c1c2SMaxim Levitsky return -1; 6249fa9c1c2SMaxim Levitsky } 6259fa9c1c2SMaxim Levitsky } 6269fa9c1c2SMaxim Levitsky 6279fa9c1c2SMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 6289fa9c1c2SMaxim Levitsky &local_err); 6299fa9c1c2SMaxim Levitsky if (local_err) { 6309fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6319fa9c1c2SMaxim Levitsky return -1; 6329fa9c1c2SMaxim Levitsky } 6339fa9c1c2SMaxim Levitsky 6349fa9c1c2SMaxim Levitsky luks->cipher_alg = 6359fa9c1c2SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 6369fa9c1c2SMaxim Levitsky luks->cipher_mode, 6379fa9c1c2SMaxim Levitsky luks->header.master_key_len, 6389fa9c1c2SMaxim Levitsky &local_err); 6399fa9c1c2SMaxim Levitsky if (local_err) { 6409fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6419fa9c1c2SMaxim Levitsky return -1; 6429fa9c1c2SMaxim Levitsky } 6439fa9c1c2SMaxim Levitsky 6449fa9c1c2SMaxim Levitsky luks->hash_alg = 6459fa9c1c2SMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 6469fa9c1c2SMaxim Levitsky &local_err); 6479fa9c1c2SMaxim Levitsky if (local_err) { 6489fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6499fa9c1c2SMaxim Levitsky return -1; 6509fa9c1c2SMaxim Levitsky } 6519fa9c1c2SMaxim Levitsky 6529fa9c1c2SMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 6539fa9c1c2SMaxim Levitsky &local_err); 6549fa9c1c2SMaxim Levitsky if (local_err) { 6559fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6569fa9c1c2SMaxim Levitsky return -1; 6579fa9c1c2SMaxim Levitsky } 6589fa9c1c2SMaxim Levitsky 6599fa9c1c2SMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 6609fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6619fa9c1c2SMaxim Levitsky error_setg(errp, "Missing IV generator hash specification"); 6629fa9c1c2SMaxim Levitsky return -1; 6639fa9c1c2SMaxim Levitsky } 6649fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = 6659fa9c1c2SMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 6669fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg, 6679fa9c1c2SMaxim Levitsky &local_err); 6689fa9c1c2SMaxim Levitsky if (local_err) { 6699fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6709fa9c1c2SMaxim Levitsky return -1; 6719fa9c1c2SMaxim Levitsky } 6729fa9c1c2SMaxim Levitsky } else { 6739fa9c1c2SMaxim Levitsky 6749fa9c1c2SMaxim Levitsky /* 6759fa9c1c2SMaxim Levitsky * Note we parsed the ivhash_name earlier in the cipher_mode 6769fa9c1c2SMaxim Levitsky * spec string even with plain/plain64 ivgens, but we 6779fa9c1c2SMaxim Levitsky * will ignore it, since it is irrelevant for these ivgens. 6789fa9c1c2SMaxim Levitsky * This is for compat with dm-crypt which will silently 6799fa9c1c2SMaxim Levitsky * ignore hash names with these ivgens rather than report 6809fa9c1c2SMaxim Levitsky * an error about the invalid usage 6819fa9c1c2SMaxim Levitsky */ 6829fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 6839fa9c1c2SMaxim Levitsky } 6849fa9c1c2SMaxim Levitsky return 0; 6859fa9c1c2SMaxim Levitsky } 6869fa9c1c2SMaxim Levitsky 6879fa9c1c2SMaxim Levitsky /* 6883994a7c9SMaxim Levitsky * Given a key slot, user password, and the master key, 6893994a7c9SMaxim Levitsky * will store the encrypted master key there, and update the 6903994a7c9SMaxim Levitsky * in-memory header. User must then write the in-memory header 6913994a7c9SMaxim Levitsky * 6923994a7c9SMaxim Levitsky * Returns: 6933994a7c9SMaxim Levitsky * 0 if the keyslot was written successfully 6943994a7c9SMaxim Levitsky * with the provided password 6953994a7c9SMaxim Levitsky * -1 if a fatal error occurred while storing the key 6963994a7c9SMaxim Levitsky */ 6973994a7c9SMaxim Levitsky static int 6983994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block, 6993994a7c9SMaxim Levitsky unsigned int slot_idx, 7003994a7c9SMaxim Levitsky const char *password, 7013994a7c9SMaxim Levitsky uint8_t *masterkey, 7023994a7c9SMaxim Levitsky uint64_t iter_time, 7033994a7c9SMaxim Levitsky QCryptoBlockWriteFunc writefunc, 7043994a7c9SMaxim Levitsky void *opaque, 7053994a7c9SMaxim Levitsky Error **errp) 7063994a7c9SMaxim Levitsky { 7073994a7c9SMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 708557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 7093994a7c9SMaxim Levitsky g_autofree uint8_t *splitkey = NULL; 7103994a7c9SMaxim Levitsky size_t splitkeylen; 7113994a7c9SMaxim Levitsky g_autofree uint8_t *slotkey = NULL; 7123994a7c9SMaxim Levitsky g_autoptr(QCryptoCipher) cipher = NULL; 7133994a7c9SMaxim Levitsky g_autoptr(QCryptoIVGen) ivgen = NULL; 7143994a7c9SMaxim Levitsky Error *local_err = NULL; 7153994a7c9SMaxim Levitsky uint64_t iters; 7163994a7c9SMaxim Levitsky int ret = -1; 7173994a7c9SMaxim Levitsky 718557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 719557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 72055a01cabSAkihiko Odaki splitkeylen = luks->header.master_key_len * slot->stripes; 72155a01cabSAkihiko Odaki 7223994a7c9SMaxim Levitsky if (qcrypto_random_bytes(slot->salt, 7233994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7243994a7c9SMaxim Levitsky errp) < 0) { 7253994a7c9SMaxim Levitsky goto cleanup; 7263994a7c9SMaxim Levitsky } 7273994a7c9SMaxim Levitsky 7283994a7c9SMaxim Levitsky /* 7293994a7c9SMaxim Levitsky * Determine how many iterations are required to 7303994a7c9SMaxim Levitsky * hash the user password while consuming 1 second of compute 7313994a7c9SMaxim Levitsky * time 7323994a7c9SMaxim Levitsky */ 7333994a7c9SMaxim Levitsky iters = qcrypto_pbkdf2_count_iters(luks->hash_alg, 7343994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7353994a7c9SMaxim Levitsky slot->salt, 7363994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7373994a7c9SMaxim Levitsky luks->header.master_key_len, 7383994a7c9SMaxim Levitsky &local_err); 7393994a7c9SMaxim Levitsky if (local_err) { 7403994a7c9SMaxim Levitsky error_propagate(errp, local_err); 7413994a7c9SMaxim Levitsky goto cleanup; 7423994a7c9SMaxim Levitsky } 7433994a7c9SMaxim Levitsky 7443994a7c9SMaxim Levitsky if (iters > (ULLONG_MAX / iter_time)) { 7453994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7463994a7c9SMaxim Levitsky "PBKDF iterations %llu too large to scale", 7473994a7c9SMaxim Levitsky (unsigned long long)iters); 7483994a7c9SMaxim Levitsky goto cleanup; 7493994a7c9SMaxim Levitsky } 7503994a7c9SMaxim Levitsky 7513994a7c9SMaxim Levitsky /* iter_time was in millis, but count_iters reported for secs */ 7523994a7c9SMaxim Levitsky iters = iters * iter_time / 1000; 7533994a7c9SMaxim Levitsky 7543994a7c9SMaxim Levitsky if (iters > UINT32_MAX) { 7553994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7563994a7c9SMaxim Levitsky "PBKDF iterations %llu larger than %u", 7573994a7c9SMaxim Levitsky (unsigned long long)iters, UINT32_MAX); 7583994a7c9SMaxim Levitsky goto cleanup; 7593994a7c9SMaxim Levitsky } 7603994a7c9SMaxim Levitsky 7613994a7c9SMaxim Levitsky slot->iterations = 7623994a7c9SMaxim Levitsky MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 7633994a7c9SMaxim Levitsky 7643994a7c9SMaxim Levitsky 7653994a7c9SMaxim Levitsky /* 7663994a7c9SMaxim Levitsky * Generate a key that we'll use to encrypt the master 7673994a7c9SMaxim Levitsky * key, from the user's password 7683994a7c9SMaxim Levitsky */ 7693994a7c9SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 7703994a7c9SMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 7713994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7723994a7c9SMaxim Levitsky slot->salt, 7733994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7743994a7c9SMaxim Levitsky slot->iterations, 7753994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7763994a7c9SMaxim Levitsky errp) < 0) { 7773994a7c9SMaxim Levitsky goto cleanup; 7783994a7c9SMaxim Levitsky } 7793994a7c9SMaxim Levitsky 7803994a7c9SMaxim Levitsky 7813994a7c9SMaxim Levitsky /* 7823994a7c9SMaxim Levitsky * Setup the encryption objects needed to encrypt the 7833994a7c9SMaxim Levitsky * master key material 7843994a7c9SMaxim Levitsky */ 7853994a7c9SMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 7863994a7c9SMaxim Levitsky luks->cipher_mode, 7873994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7883994a7c9SMaxim Levitsky errp); 7893994a7c9SMaxim Levitsky if (!cipher) { 7903994a7c9SMaxim Levitsky goto cleanup; 7913994a7c9SMaxim Levitsky } 7923994a7c9SMaxim Levitsky 7933994a7c9SMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 7943994a7c9SMaxim Levitsky luks->ivgen_cipher_alg, 7953994a7c9SMaxim Levitsky luks->ivgen_hash_alg, 7963994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7973994a7c9SMaxim Levitsky errp); 7983994a7c9SMaxim Levitsky if (!ivgen) { 7993994a7c9SMaxim Levitsky goto cleanup; 8003994a7c9SMaxim Levitsky } 8013994a7c9SMaxim Levitsky 8023994a7c9SMaxim Levitsky /* 8033994a7c9SMaxim Levitsky * Before storing the master key, we need to vastly 8043994a7c9SMaxim Levitsky * increase its size, as protection against forensic 8053994a7c9SMaxim Levitsky * disk data recovery 8063994a7c9SMaxim Levitsky */ 8073994a7c9SMaxim Levitsky splitkey = g_new0(uint8_t, splitkeylen); 8083994a7c9SMaxim Levitsky 8093994a7c9SMaxim Levitsky if (qcrypto_afsplit_encode(luks->hash_alg, 8103994a7c9SMaxim Levitsky luks->header.master_key_len, 8113994a7c9SMaxim Levitsky slot->stripes, 8123994a7c9SMaxim Levitsky masterkey, 8133994a7c9SMaxim Levitsky splitkey, 8143994a7c9SMaxim Levitsky errp) < 0) { 8153994a7c9SMaxim Levitsky goto cleanup; 8163994a7c9SMaxim Levitsky } 8173994a7c9SMaxim Levitsky 8183994a7c9SMaxim Levitsky /* 8193994a7c9SMaxim Levitsky * Now we encrypt the split master key with the key generated 8203994a7c9SMaxim Levitsky * from the user's password, before storing it 8213994a7c9SMaxim Levitsky */ 8223994a7c9SMaxim Levitsky if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 8233994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8243994a7c9SMaxim Levitsky 0, 8253994a7c9SMaxim Levitsky splitkey, 8263994a7c9SMaxim Levitsky splitkeylen, 8273994a7c9SMaxim Levitsky errp) < 0) { 8283994a7c9SMaxim Levitsky goto cleanup; 8293994a7c9SMaxim Levitsky } 8303994a7c9SMaxim Levitsky 8313994a7c9SMaxim Levitsky /* Write out the slot's master key material. */ 8323994a7c9SMaxim Levitsky if (writefunc(block, 8333994a7c9SMaxim Levitsky slot->key_offset_sector * 8343994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8353994a7c9SMaxim Levitsky splitkey, splitkeylen, 8363994a7c9SMaxim Levitsky opaque, 837757dda54SAlberto Faria errp) < 0) { 8383994a7c9SMaxim Levitsky goto cleanup; 8393994a7c9SMaxim Levitsky } 8403994a7c9SMaxim Levitsky 8413994a7c9SMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 8423994a7c9SMaxim Levitsky 8433994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) { 8443994a7c9SMaxim Levitsky goto cleanup; 8453994a7c9SMaxim Levitsky } 8463994a7c9SMaxim Levitsky 8473994a7c9SMaxim Levitsky ret = 0; 8483994a7c9SMaxim Levitsky 8493994a7c9SMaxim Levitsky cleanup: 8503994a7c9SMaxim Levitsky if (slotkey) { 8513994a7c9SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 8523994a7c9SMaxim Levitsky } 8533994a7c9SMaxim Levitsky if (splitkey) { 8543994a7c9SMaxim Levitsky memset(splitkey, 0, splitkeylen); 8553994a7c9SMaxim Levitsky } 8563994a7c9SMaxim Levitsky return ret; 8573994a7c9SMaxim Levitsky } 8583994a7c9SMaxim Levitsky 8593994a7c9SMaxim Levitsky /* 8603e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 8613e308f20SDaniel P. Berrange * the master encryption key from the key slot. 8623e308f20SDaniel P. Berrange * 8633e308f20SDaniel P. Berrange * Returns: 8643e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 8653e308f20SDaniel P. Berrange * with the provided password 8663e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 8673e308f20SDaniel P. Berrange * with the provided password 8683e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 8693e308f20SDaniel P. Berrange */ 8703e308f20SDaniel P. Berrange static int 8713e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 8727e60a6f5SMaxim Levitsky size_t slot_idx, 8733e308f20SDaniel P. Berrange const char *password, 8743e308f20SDaniel P. Berrange uint8_t *masterkey, 8753e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 8763e308f20SDaniel P. Berrange void *opaque, 8773e308f20SDaniel P. Berrange Error **errp) 8783e308f20SDaniel P. Berrange { 8793e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 880557d2bdcSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot; 88157b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 8823e308f20SDaniel P. Berrange size_t splitkeylen; 88357b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 884757dda54SAlberto Faria int rv; 88557b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 8863e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 88757b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 8883e308f20SDaniel P. Berrange size_t niv; 8893e308f20SDaniel P. Berrange 890557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 891557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 8923e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 8933e308f20SDaniel P. Berrange return 0; 8943e308f20SDaniel P. Berrange } 8953e308f20SDaniel P. Berrange 8961ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 8973e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 8981ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 8993e308f20SDaniel P. Berrange 9003e308f20SDaniel P. Berrange /* 9013e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 9023e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 9033e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 9043e308f20SDaniel P. Berrange * the key is correct and validate the results of 9053e308f20SDaniel P. Berrange * decryption later. 9063e308f20SDaniel P. Berrange */ 9079d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 9083e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 9093e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 9103e308f20SDaniel P. Berrange slot->iterations, 9111ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 9123e308f20SDaniel P. Berrange errp) < 0) { 91357b9f113SDaniel P. Berrangé return -1; 9143e308f20SDaniel P. Berrange } 9153e308f20SDaniel P. Berrange 9163e308f20SDaniel P. Berrange /* 9173e308f20SDaniel P. Berrange * We need to read the master key material from the 9183e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 9193e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 9203e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 9213e308f20SDaniel P. Berrange * then encrypted. 9223e308f20SDaniel P. Berrange */ 9233e308f20SDaniel P. Berrange rv = readfunc(block, 924f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9253e308f20SDaniel P. Berrange splitkey, splitkeylen, 926e4a3507eSDaniel P. Berrange opaque, 92737509233SFam Zheng errp); 9283e308f20SDaniel P. Berrange if (rv < 0) { 92957b9f113SDaniel P. Berrangé return -1; 9303e308f20SDaniel P. Berrange } 9313e308f20SDaniel P. Berrange 9323e308f20SDaniel P. Berrange 9333e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 9343e308f20SDaniel P. Berrange * the split master key material */ 9359d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 9369d80e59dSMaxim Levitsky luks->cipher_mode, 9379d80e59dSMaxim Levitsky possiblekey, 9389d80e59dSMaxim Levitsky luks->header.master_key_len, 9393e308f20SDaniel P. Berrange errp); 9403e308f20SDaniel P. Berrange if (!cipher) { 94157b9f113SDaniel P. Berrangé return -1; 9423e308f20SDaniel P. Berrange } 9433e308f20SDaniel P. Berrange 9449d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 9459d80e59dSMaxim Levitsky luks->cipher_mode); 9469d80e59dSMaxim Levitsky 9479d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 9489d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 9499d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 9509d80e59dSMaxim Levitsky possiblekey, 9519d80e59dSMaxim Levitsky luks->header.master_key_len, 9523e308f20SDaniel P. Berrange errp); 9533e308f20SDaniel P. Berrange if (!ivgen) { 95457b9f113SDaniel P. Berrangé return -1; 9553e308f20SDaniel P. Berrange } 9563e308f20SDaniel P. Berrange 9573e308f20SDaniel P. Berrange 9583e308f20SDaniel P. Berrange /* 9593e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 9603e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 9613e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 9623e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 9633e308f20SDaniel P. Berrange * key crosses a sector boundary. 9643e308f20SDaniel P. Berrange */ 9650270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 9663e308f20SDaniel P. Berrange niv, 9673e308f20SDaniel P. Berrange ivgen, 9683e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9693e308f20SDaniel P. Berrange 0, 9703e308f20SDaniel P. Berrange splitkey, 9713e308f20SDaniel P. Berrange splitkeylen, 9723e308f20SDaniel P. Berrange errp) < 0) { 97357b9f113SDaniel P. Berrangé return -1; 9743e308f20SDaniel P. Berrange } 9753e308f20SDaniel P. Berrange 9763e308f20SDaniel P. Berrange /* 9773e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 9783e308f20SDaniel P. Berrange * it back together to get the actual master key. 9793e308f20SDaniel P. Berrange */ 9809d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 9811ddd52e4SMaxim Levitsky luks->header.master_key_len, 9823e308f20SDaniel P. Berrange slot->stripes, 9833e308f20SDaniel P. Berrange splitkey, 9843e308f20SDaniel P. Berrange masterkey, 9853e308f20SDaniel P. Berrange errp) < 0) { 98657b9f113SDaniel P. Berrangé return -1; 9873e308f20SDaniel P. Berrange } 9883e308f20SDaniel P. Berrange 9893e308f20SDaniel P. Berrange 9903e308f20SDaniel P. Berrange /* 9913e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 9923e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 9933e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 9943e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 9953e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 9963e308f20SDaniel P. Berrange * header 9973e308f20SDaniel P. Berrange */ 9989d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 9991ddd52e4SMaxim Levitsky masterkey, 10001ddd52e4SMaxim Levitsky luks->header.master_key_len, 10013e308f20SDaniel P. Berrange luks->header.master_key_salt, 10023e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10033e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10041ddd52e4SMaxim Levitsky keydigest, 10051ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 10063e308f20SDaniel P. Berrange errp) < 0) { 100757b9f113SDaniel P. Berrangé return -1; 10083e308f20SDaniel P. Berrange } 10093e308f20SDaniel P. Berrange 10103e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 10113e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 10123e308f20SDaniel P. Berrange /* Success, we got the right master key */ 101357b9f113SDaniel P. Berrangé return 1; 10143e308f20SDaniel P. Berrange } 10153e308f20SDaniel P. Berrange 10163e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 10173e308f20SDaniel P. Berrange * tell caller to try another slot */ 101857b9f113SDaniel P. Berrangé return 0; 10193e308f20SDaniel P. Berrange } 10203e308f20SDaniel P. Berrange 10213e308f20SDaniel P. Berrange 10223e308f20SDaniel P. Berrange /* 10233e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 10243e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 10253e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 10263e308f20SDaniel P. Berrange * 10273e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 10283e308f20SDaniel P. Berrange */ 10293e308f20SDaniel P. Berrange static int 10303e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 10313e308f20SDaniel P. Berrange const char *password, 10321ddd52e4SMaxim Levitsky uint8_t *masterkey, 10333e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 10343e308f20SDaniel P. Berrange void *opaque, 10353e308f20SDaniel P. Berrange Error **errp) 10363e308f20SDaniel P. Berrange { 10373e308f20SDaniel P. Berrange size_t i; 10383e308f20SDaniel P. Berrange int rv; 10393e308f20SDaniel P. Berrange 10403e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10413e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 10427e60a6f5SMaxim Levitsky i, 10433e308f20SDaniel P. Berrange password, 10441ddd52e4SMaxim Levitsky masterkey, 10453e308f20SDaniel P. Berrange readfunc, 10463e308f20SDaniel P. Berrange opaque, 10473e308f20SDaniel P. Berrange errp); 10483e308f20SDaniel P. Berrange if (rv < 0) { 10493e308f20SDaniel P. Berrange goto error; 10503e308f20SDaniel P. Berrange } 10513e308f20SDaniel P. Berrange if (rv == 1) { 10523e308f20SDaniel P. Berrange return 0; 10533e308f20SDaniel P. Berrange } 10543e308f20SDaniel P. Berrange } 10553e308f20SDaniel P. Berrange 10563e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 10573e308f20SDaniel P. Berrange error: 10583e308f20SDaniel P. Berrange return -1; 10593e308f20SDaniel P. Berrange } 10603e308f20SDaniel P. Berrange 1061557d2bdcSMaxim Levitsky /* 1062557d2bdcSMaxim Levitsky * Returns true if a slot i is marked as active 1063557d2bdcSMaxim Levitsky * (contains encrypted copy of the master key) 1064557d2bdcSMaxim Levitsky */ 1065557d2bdcSMaxim Levitsky static bool 1066557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, 1067557d2bdcSMaxim Levitsky unsigned int slot_idx) 1068557d2bdcSMaxim Levitsky { 1069557d2bdcSMaxim Levitsky uint32_t val; 1070557d2bdcSMaxim Levitsky 1071557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1072557d2bdcSMaxim Levitsky val = luks->header.key_slots[slot_idx].active; 1073557d2bdcSMaxim Levitsky return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1074557d2bdcSMaxim Levitsky } 1075557d2bdcSMaxim Levitsky 1076557d2bdcSMaxim Levitsky /* 1077557d2bdcSMaxim Levitsky * Returns the number of slots that are marked as active 1078557d2bdcSMaxim Levitsky * (slots that contain encrypted copy of the master key) 1079557d2bdcSMaxim Levitsky */ 1080557d2bdcSMaxim Levitsky static unsigned int 1081557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) 1082557d2bdcSMaxim Levitsky { 1083557d2bdcSMaxim Levitsky size_t i = 0; 1084557d2bdcSMaxim Levitsky unsigned int ret = 0; 1085557d2bdcSMaxim Levitsky 1086557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1087557d2bdcSMaxim Levitsky if (qcrypto_block_luks_slot_active(luks, i)) { 1088557d2bdcSMaxim Levitsky ret++; 1089557d2bdcSMaxim Levitsky } 1090557d2bdcSMaxim Levitsky } 1091557d2bdcSMaxim Levitsky return ret; 1092557d2bdcSMaxim Levitsky } 1093557d2bdcSMaxim Levitsky 1094557d2bdcSMaxim Levitsky /* 1095557d2bdcSMaxim Levitsky * Finds first key slot which is not active 1096557d2bdcSMaxim Levitsky * Returns the key slot index, or -1 if it doesn't exist 1097557d2bdcSMaxim Levitsky */ 1098557d2bdcSMaxim Levitsky static int 1099557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) 1100557d2bdcSMaxim Levitsky { 1101557d2bdcSMaxim Levitsky size_t i; 1102557d2bdcSMaxim Levitsky 1103557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1104557d2bdcSMaxim Levitsky if (!qcrypto_block_luks_slot_active(luks, i)) { 1105557d2bdcSMaxim Levitsky return i; 1106557d2bdcSMaxim Levitsky } 1107557d2bdcSMaxim Levitsky } 1108557d2bdcSMaxim Levitsky return -1; 1109557d2bdcSMaxim Levitsky } 1110557d2bdcSMaxim Levitsky 1111557d2bdcSMaxim Levitsky /* 1112557d2bdcSMaxim Levitsky * Erases an keyslot given its index 1113557d2bdcSMaxim Levitsky * Returns: 1114557d2bdcSMaxim Levitsky * 0 if the keyslot was erased successfully 1115557d2bdcSMaxim Levitsky * -1 if a error occurred while erasing the keyslot 1116557d2bdcSMaxim Levitsky * 1117557d2bdcSMaxim Levitsky */ 1118557d2bdcSMaxim Levitsky static int 1119557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block, 1120557d2bdcSMaxim Levitsky unsigned int slot_idx, 1121557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1122557d2bdcSMaxim Levitsky void *opaque, 1123557d2bdcSMaxim Levitsky Error **errp) 1124557d2bdcSMaxim Levitsky { 1125557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1126557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 1127557d2bdcSMaxim Levitsky g_autofree uint8_t *garbagesplitkey = NULL; 1128557d2bdcSMaxim Levitsky size_t splitkeylen; 1129557d2bdcSMaxim Levitsky size_t i; 1130557d2bdcSMaxim Levitsky Error *local_err = NULL; 1131557d2bdcSMaxim Levitsky int ret; 1132557d2bdcSMaxim Levitsky 1133557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1134557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 1135557d2bdcSMaxim Levitsky 1136557d2bdcSMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 1137557d2bdcSMaxim Levitsky assert(splitkeylen > 0); 1138557d2bdcSMaxim Levitsky 1139557d2bdcSMaxim Levitsky garbagesplitkey = g_new0(uint8_t, splitkeylen); 1140557d2bdcSMaxim Levitsky 1141557d2bdcSMaxim Levitsky /* Reset the key slot header */ 1142557d2bdcSMaxim Levitsky memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); 1143557d2bdcSMaxim Levitsky slot->iterations = 0; 1144557d2bdcSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 1145557d2bdcSMaxim Levitsky 1146557d2bdcSMaxim Levitsky ret = qcrypto_block_luks_store_header(block, writefunc, 1147557d2bdcSMaxim Levitsky opaque, &local_err); 1148557d2bdcSMaxim Levitsky 1149557d2bdcSMaxim Levitsky if (ret < 0) { 1150557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1151557d2bdcSMaxim Levitsky } 1152557d2bdcSMaxim Levitsky /* 1153557d2bdcSMaxim Levitsky * Now try to erase the key material, even if the header 1154557d2bdcSMaxim Levitsky * update failed 1155557d2bdcSMaxim Levitsky */ 1156557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { 1157557d2bdcSMaxim Levitsky if (qcrypto_random_bytes(garbagesplitkey, 1158557d2bdcSMaxim Levitsky splitkeylen, &local_err) < 0) { 1159557d2bdcSMaxim Levitsky /* 1160557d2bdcSMaxim Levitsky * If we failed to get the random data, still write 1161557d2bdcSMaxim Levitsky * at least zeros to the key slot at least once 1162557d2bdcSMaxim Levitsky */ 1163557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1164557d2bdcSMaxim Levitsky 1165557d2bdcSMaxim Levitsky if (i > 0) { 1166557d2bdcSMaxim Levitsky return -1; 1167557d2bdcSMaxim Levitsky } 1168557d2bdcSMaxim Levitsky } 1169557d2bdcSMaxim Levitsky if (writefunc(block, 1170557d2bdcSMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 1171557d2bdcSMaxim Levitsky garbagesplitkey, 1172557d2bdcSMaxim Levitsky splitkeylen, 1173557d2bdcSMaxim Levitsky opaque, 1174757dda54SAlberto Faria &local_err) < 0) { 1175557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1176557d2bdcSMaxim Levitsky return -1; 1177557d2bdcSMaxim Levitsky } 1178557d2bdcSMaxim Levitsky } 1179557d2bdcSMaxim Levitsky return ret; 1180557d2bdcSMaxim Levitsky } 11813e308f20SDaniel P. Berrange 11823e308f20SDaniel P. Berrange static int 11833e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 11843e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 11851cd9a787SDaniel P. Berrange const char *optprefix, 11863e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 11873e308f20SDaniel P. Berrange void *opaque, 11883e308f20SDaniel P. Berrange unsigned int flags, 1189c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 11903e308f20SDaniel P. Berrange Error **errp) 11913e308f20SDaniel P. Berrange { 11929d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 119357b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 119457b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 11953e308f20SDaniel P. Berrange 11963e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 11973e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 11981cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 11991cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 12003e308f20SDaniel P. Berrange return -1; 12013e308f20SDaniel P. Berrange } 12023e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 12033e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 12043e308f20SDaniel P. Berrange if (!password) { 12053e308f20SDaniel P. Berrange return -1; 12063e308f20SDaniel P. Berrange } 12073e308f20SDaniel P. Berrange } 12083e308f20SDaniel P. Berrange 12093e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 12103e308f20SDaniel P. Berrange block->opaque = luks; 1211557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 12123e308f20SDaniel P. Berrange 1213dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 12143e308f20SDaniel P. Berrange goto fail; 12153e308f20SDaniel P. Berrange } 12163e308f20SDaniel P. Berrange 12179fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_check_header(luks, errp) < 0) { 12183e308f20SDaniel P. Berrange goto fail; 12193e308f20SDaniel P. Berrange } 12203e308f20SDaniel P. Berrange 12219fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_parse_header(luks, errp) < 0) { 12223e308f20SDaniel P. Berrange goto fail; 12233e308f20SDaniel P. Berrange } 12243e308f20SDaniel P. Berrange 12253e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12263e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 12273e308f20SDaniel P. Berrange * and unlock the master key from that slot. 12283e308f20SDaniel P. Berrange */ 12291ddd52e4SMaxim Levitsky 12301ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 12311ddd52e4SMaxim Levitsky 12323e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 12333e308f20SDaniel P. Berrange password, 12341ddd52e4SMaxim Levitsky masterkey, 12353e308f20SDaniel P. Berrange readfunc, opaque, 12363e308f20SDaniel P. Berrange errp) < 0) { 12373e308f20SDaniel P. Berrange goto fail; 12383e308f20SDaniel P. Berrange } 12393e308f20SDaniel P. Berrange 12403e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 12413e308f20SDaniel P. Berrange * block device payload decryption objects 12423e308f20SDaniel P. Berrange */ 12439d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 12449d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 12459d80e59dSMaxim Levitsky luks->cipher_mode); 12469d80e59dSMaxim Levitsky 12479d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 12489d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 12499d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 12501ddd52e4SMaxim Levitsky masterkey, 12511ddd52e4SMaxim Levitsky luks->header.master_key_len, 12523e308f20SDaniel P. Berrange errp); 12533e308f20SDaniel P. Berrange if (!block->ivgen) { 12543e308f20SDaniel P. Berrange goto fail; 12553e308f20SDaniel P. Berrange } 12563e308f20SDaniel P. Berrange 125761dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 12589d80e59dSMaxim Levitsky luks->cipher_alg, 12599d80e59dSMaxim Levitsky luks->cipher_mode, 12601ddd52e4SMaxim Levitsky masterkey, 12611ddd52e4SMaxim Levitsky luks->header.master_key_len, 12621ddd52e4SMaxim Levitsky n_threads, 126361dd8a9aSMaxim Levitsky errp) < 0) { 12643e308f20SDaniel P. Berrange goto fail; 12653e308f20SDaniel P. Berrange } 12663e308f20SDaniel P. Berrange } 12673e308f20SDaniel P. Berrange 1268850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1269f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1270850f49deSDaniel P. Berrange block->sector_size; 12713e308f20SDaniel P. Berrange 12723e308f20SDaniel P. Berrange return 0; 12733e308f20SDaniel P. Berrange 12743e308f20SDaniel P. Berrange fail: 1275c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 12763e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 1277557d2bdcSMaxim Levitsky g_free(luks->secret); 12783e308f20SDaniel P. Berrange g_free(luks); 127961dd8a9aSMaxim Levitsky return -1; 12803e308f20SDaniel P. Berrange } 12813e308f20SDaniel P. Berrange 12823e308f20SDaniel P. Berrange 12832ef950f9SFam Zheng static void 12842ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 12853e308f20SDaniel P. Berrange { 12862ef950f9SFam Zheng QemuUUID uuid; 12872ef950f9SFam Zheng qemu_uuid_generate(&uuid); 12882ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 12893e308f20SDaniel P. Berrange } 12903e308f20SDaniel P. Berrange 12913e308f20SDaniel P. Berrange static int 12923e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 12933e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 12941cd9a787SDaniel P. Berrange const char *optprefix, 12953e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 12963e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 12973e308f20SDaniel P. Berrange void *opaque, 12983e308f20SDaniel P. Berrange Error **errp) 12993e308f20SDaniel P. Berrange { 13003e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 13013e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 13023e308f20SDaniel P. Berrange Error *local_err = NULL; 130357b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 1304bd56a55aSMaxim Levitsky size_t header_sectors; 1305bd56a55aSMaxim Levitsky size_t split_key_sectors; 13063e308f20SDaniel P. Berrange size_t i; 130757b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 13083e308f20SDaniel P. Berrange const char *cipher_alg; 13093e308f20SDaniel P. Berrange const char *cipher_mode; 13103e308f20SDaniel P. Berrange const char *ivgen_alg; 13113e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 13123e308f20SDaniel P. Berrange const char *hash_alg; 131357b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 131459b060beSDaniel P. Berrange uint64_t iters; 13153e308f20SDaniel P. Berrange 13163e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 13173bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 1318557d2bdcSMaxim Levitsky luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 13193bd18890SDaniel P. Berrange } 13203e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 13213e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 13223e308f20SDaniel P. Berrange } 13233e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 13243e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 13253e308f20SDaniel P. Berrange } 13263e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 13273e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 13283e308f20SDaniel P. Berrange } 13293e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 13303e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 13313e308f20SDaniel P. Berrange } 13328b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 13338b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 13348b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 13358b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 13368b7cdba3SDaniel P. Berrange } 13378b7cdba3SDaniel P. Berrange } 13389d80e59dSMaxim Levitsky 13399d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 13409d80e59dSMaxim Levitsky block->opaque = luks; 13419d80e59dSMaxim Levitsky 13429d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 13439d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 13449d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 13459d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 13469d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 13479d80e59dSMaxim Levitsky 13489d80e59dSMaxim Levitsky 13498b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 13508b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 13518b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 13523e308f20SDaniel P. Berrange 13533e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 13541cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 13551cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 13569d80e59dSMaxim Levitsky goto error; 13573e308f20SDaniel P. Berrange } 1358557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 1359557d2bdcSMaxim Levitsky 13603e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 13613e308f20SDaniel P. Berrange if (!password) { 13629d80e59dSMaxim Levitsky goto error; 13633e308f20SDaniel P. Berrange } 13643e308f20SDaniel P. Berrange 13653e308f20SDaniel P. Berrange 13663e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 13673e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 13683e308f20SDaniel P. Berrange 13693e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 13703e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 13713e308f20SDaniel P. Berrange * it out to disk 13723e308f20SDaniel P. Berrange */ 13733e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 13742ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 13753e308f20SDaniel P. Berrange 13763e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 13773e308f20SDaniel P. Berrange errp); 13783e308f20SDaniel P. Berrange if (!cipher_alg) { 13793e308f20SDaniel P. Berrange goto error; 13803e308f20SDaniel P. Berrange } 13813e308f20SDaniel P. Berrange 1382977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 1383977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 13843e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 1385977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 13863e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 13873e308f20SDaniel P. Berrange ivgen_hash_alg); 13883e308f20SDaniel P. Berrange } else { 13893e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 13903e308f20SDaniel P. Berrange } 1391977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 13923e308f20SDaniel P. Berrange 13933e308f20SDaniel P. Berrange 13943e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 13953e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 13963e308f20SDaniel P. Berrange cipher_alg); 13973e308f20SDaniel P. Berrange goto error; 13983e308f20SDaniel P. Berrange } 13993e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 14003e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 14013e308f20SDaniel P. Berrange cipher_mode_spec); 14023e308f20SDaniel P. Berrange goto error; 14033e308f20SDaniel P. Berrange } 14043e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 14053e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 14063e308f20SDaniel P. Berrange hash_alg); 14073e308f20SDaniel P. Berrange goto error; 14083e308f20SDaniel P. Berrange } 14093e308f20SDaniel P. Berrange 14103e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 14119d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 14129d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 14133e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 14143e308f20SDaniel P. Berrange &local_err); 14153e308f20SDaniel P. Berrange if (local_err) { 14163e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14173e308f20SDaniel P. Berrange goto error; 14183e308f20SDaniel P. Berrange } 14193e308f20SDaniel P. Berrange } else { 14209d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 14213e308f20SDaniel P. Berrange } 14223e308f20SDaniel P. Berrange 14233e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 14243e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 14253e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 14263e308f20SDaniel P. Berrange 1427f0d3c362SMaxim Levitsky luks->header.master_key_len = 1428f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 1429f0d3c362SMaxim Levitsky 14303e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 1431f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 14323e308f20SDaniel P. Berrange } 14333e308f20SDaniel P. Berrange 14343e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 14353e308f20SDaniel P. Berrange * with PBKDF later 14363e308f20SDaniel P. Berrange */ 14373e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 14383e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 14393e308f20SDaniel P. Berrange errp) < 0) { 14403e308f20SDaniel P. Berrange goto error; 14413e308f20SDaniel P. Berrange } 14423e308f20SDaniel P. Berrange 14433e308f20SDaniel P. Berrange /* Generate random master key */ 1444f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 14453e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 1446f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 14473e308f20SDaniel P. Berrange goto error; 14483e308f20SDaniel P. Berrange } 14493e308f20SDaniel P. Berrange 14503e308f20SDaniel P. Berrange 14513e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1452c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1453c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1454f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 14553e308f20SDaniel P. Berrange goto error; 14563e308f20SDaniel P. Berrange } 14573e308f20SDaniel P. Berrange 14583e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 14593e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 14603e308f20SDaniel P. Berrange luks_opts.cipher_mode); 14613e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 14629d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 14633e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1464f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14653e308f20SDaniel P. Berrange errp); 14663e308f20SDaniel P. Berrange 14673e308f20SDaniel P. Berrange if (!block->ivgen) { 14683e308f20SDaniel P. Berrange goto error; 14693e308f20SDaniel P. Berrange } 14703e308f20SDaniel P. Berrange 14713e308f20SDaniel P. Berrange 14723e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 14733e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 14743e308f20SDaniel P. Berrange */ 147559b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1476f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14773e308f20SDaniel P. Berrange luks->header.master_key_salt, 14783e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1479e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 14803e308f20SDaniel P. Berrange &local_err); 14813e308f20SDaniel P. Berrange if (local_err) { 14823e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14833e308f20SDaniel P. Berrange goto error; 14843e308f20SDaniel P. Berrange } 14853e308f20SDaniel P. Berrange 14863bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 14873bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 14883bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 14893bd18890SDaniel P. Berrange (unsigned long long)iters); 14903bd18890SDaniel P. Berrange goto error; 14913bd18890SDaniel P. Berrange } 14923bd18890SDaniel P. Berrange 14933bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 14943bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 14953bd18890SDaniel P. Berrange 14963e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 14973e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 14983e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 14993e308f20SDaniel P. Berrange * in total time to check all keys */ 150059b060beSDaniel P. Berrange iters /= 8; 150159b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 150259b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 150359b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 150459b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 150559b060beSDaniel P. Berrange goto error; 150659b060beSDaniel P. Berrange } 150759b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 150859b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 15093e308f20SDaniel P. Berrange 15103e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 15113e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 15123e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 15133e308f20SDaniel P. Berrange * valid master key 15143e308f20SDaniel P. Berrange */ 15153e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1516f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 15173e308f20SDaniel P. Berrange luks->header.master_key_salt, 15183e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 15193e308f20SDaniel P. Berrange luks->header.master_key_iterations, 15203e308f20SDaniel P. Berrange luks->header.master_key_digest, 15213e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 15223e308f20SDaniel P. Berrange errp) < 0) { 15233e308f20SDaniel P. Berrange goto error; 15243e308f20SDaniel P. Berrange } 15253e308f20SDaniel P. Berrange 1526bd56a55aSMaxim Levitsky /* start with the sector that follows the header*/ 1527bd56a55aSMaxim Levitsky header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 1528bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 15293e308f20SDaniel P. Berrange 1530bd56a55aSMaxim Levitsky split_key_sectors = 1531bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 1532bd56a55aSMaxim Levitsky header_sectors, 1533bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_STRIPES); 1534bd56a55aSMaxim Levitsky 15353e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1536bd56a55aSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i]; 1537bd56a55aSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 15383e308f20SDaniel P. Berrange 1539bd56a55aSMaxim Levitsky slot->key_offset_sector = header_sectors + i * split_key_sectors; 1540bd56a55aSMaxim Levitsky slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 15413e308f20SDaniel P. Berrange } 15423e308f20SDaniel P. Berrange 15433e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 15443e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 15453e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 15463e308f20SDaniel P. Berrange * to the nearest sector */ 1547bd56a55aSMaxim Levitsky luks->header.payload_offset_sector = header_sectors + 1548bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors; 15493e308f20SDaniel P. Berrange 1550850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1551f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1552850f49deSDaniel P. Berrange block->sector_size; 15533e308f20SDaniel P. Berrange 15543e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1555e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 15563e308f20SDaniel P. Berrange if (local_err) { 15573e308f20SDaniel P. Berrange error_propagate(errp, local_err); 15583e308f20SDaniel P. Berrange goto error; 15593e308f20SDaniel P. Berrange } 15603e308f20SDaniel P. Berrange 15613e308f20SDaniel P. Berrange 15623994a7c9SMaxim Levitsky /* populate the slot 0 with the password encrypted master key*/ 15633994a7c9SMaxim Levitsky /* This will also store the header */ 15643994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_key(block, 15653994a7c9SMaxim Levitsky 0, 15663994a7c9SMaxim Levitsky password, 15673994a7c9SMaxim Levitsky masterkey, 15683994a7c9SMaxim Levitsky luks_opts.iter_time, 15693994a7c9SMaxim Levitsky writefunc, 1570e4a3507eSDaniel P. Berrange opaque, 15713994a7c9SMaxim Levitsky errp) < 0) { 15723e308f20SDaniel P. Berrange goto error; 15733e308f20SDaniel P. Berrange } 15743e308f20SDaniel P. Berrange 1575f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15763e308f20SDaniel P. Berrange 15773e308f20SDaniel P. Berrange return 0; 15783e308f20SDaniel P. Berrange 15793e308f20SDaniel P. Berrange error: 15803e308f20SDaniel P. Berrange if (masterkey) { 1581f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15823e308f20SDaniel P. Berrange } 15833e308f20SDaniel P. Berrange 1584c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1585b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1586b640adcaSVladimir Sementsov-Ogievskiy 1587557d2bdcSMaxim Levitsky g_free(luks->secret); 15883e308f20SDaniel P. Berrange g_free(luks); 15893e308f20SDaniel P. Berrange return -1; 15903e308f20SDaniel P. Berrange } 15913e308f20SDaniel P. Berrange 1592557d2bdcSMaxim Levitsky static int 1593557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, 1594557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1595557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1596557d2bdcSMaxim Levitsky void *opaque, 1597557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1598557d2bdcSMaxim Levitsky bool force, 1599557d2bdcSMaxim Levitsky Error **errp) 1600557d2bdcSMaxim Levitsky { 1601557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1602557d2bdcSMaxim Levitsky uint64_t iter_time = opts_luks->has_iter_time ? 1603557d2bdcSMaxim Levitsky opts_luks->iter_time : 1604557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1605557d2bdcSMaxim Levitsky int keyslot; 1606557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1607557d2bdcSMaxim Levitsky g_autofree char *new_password = NULL; 1608557d2bdcSMaxim Levitsky g_autofree uint8_t *master_key = NULL; 1609557d2bdcSMaxim Levitsky 161016110c8bSMarkus Armbruster char *secret = opts_luks->secret ?: luks->secret; 1611557d2bdcSMaxim Levitsky 161216110c8bSMarkus Armbruster if (!opts_luks->new_secret) { 1613557d2bdcSMaxim Levitsky error_setg(errp, "'new-secret' is required to activate a keyslot"); 1614557d2bdcSMaxim Levitsky return -1; 1615557d2bdcSMaxim Levitsky } 161616110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1617557d2bdcSMaxim Levitsky error_setg(errp, 1618557d2bdcSMaxim Levitsky "'old-secret' must not be given when activating keyslots"); 1619557d2bdcSMaxim Levitsky return -1; 1620557d2bdcSMaxim Levitsky } 1621557d2bdcSMaxim Levitsky 1622557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1623557d2bdcSMaxim Levitsky keyslot = opts_luks->keyslot; 1624557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1625557d2bdcSMaxim Levitsky error_setg(errp, 1626557d2bdcSMaxim Levitsky "Invalid keyslot %u specified, must be between 0 and %u", 1627557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1628557d2bdcSMaxim Levitsky return -1; 1629557d2bdcSMaxim Levitsky } 1630557d2bdcSMaxim Levitsky } else { 1631557d2bdcSMaxim Levitsky keyslot = qcrypto_block_luks_find_free_keyslot(luks); 1632557d2bdcSMaxim Levitsky if (keyslot == -1) { 1633557d2bdcSMaxim Levitsky error_setg(errp, 1634557d2bdcSMaxim Levitsky "Can't add a keyslot - all keyslots are in use"); 1635557d2bdcSMaxim Levitsky return -1; 1636557d2bdcSMaxim Levitsky } 1637557d2bdcSMaxim Levitsky } 1638557d2bdcSMaxim Levitsky 1639557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { 1640557d2bdcSMaxim Levitsky error_setg(errp, 1641557d2bdcSMaxim Levitsky "Refusing to overwrite active keyslot %i - " 1642557d2bdcSMaxim Levitsky "please erase it first", 1643557d2bdcSMaxim Levitsky keyslot); 1644557d2bdcSMaxim Levitsky return -1; 1645557d2bdcSMaxim Levitsky } 1646557d2bdcSMaxim Levitsky 1647557d2bdcSMaxim Levitsky /* Locate the password that will be used to retrieve the master key */ 1648557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(secret, errp); 1649557d2bdcSMaxim Levitsky if (!old_password) { 1650557d2bdcSMaxim Levitsky return -1; 1651557d2bdcSMaxim Levitsky } 1652557d2bdcSMaxim Levitsky 1653557d2bdcSMaxim Levitsky /* Retrieve the master key */ 1654557d2bdcSMaxim Levitsky master_key = g_new0(uint8_t, luks->header.master_key_len); 1655557d2bdcSMaxim Levitsky 1656557d2bdcSMaxim Levitsky if (qcrypto_block_luks_find_key(block, old_password, master_key, 1657557d2bdcSMaxim Levitsky readfunc, opaque, errp) < 0) { 1658557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to retrieve the master key"); 1659557d2bdcSMaxim Levitsky return -1; 1660557d2bdcSMaxim Levitsky } 1661557d2bdcSMaxim Levitsky 1662557d2bdcSMaxim Levitsky /* Locate the new password*/ 1663557d2bdcSMaxim Levitsky new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); 1664557d2bdcSMaxim Levitsky if (!new_password) { 1665557d2bdcSMaxim Levitsky return -1; 1666557d2bdcSMaxim Levitsky } 1667557d2bdcSMaxim Levitsky 1668557d2bdcSMaxim Levitsky /* Now set the new keyslots */ 1669557d2bdcSMaxim Levitsky if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, 1670557d2bdcSMaxim Levitsky iter_time, writefunc, opaque, errp)) { 1671557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to write to keyslot %i", keyslot); 1672557d2bdcSMaxim Levitsky return -1; 1673557d2bdcSMaxim Levitsky } 1674557d2bdcSMaxim Levitsky return 0; 1675557d2bdcSMaxim Levitsky } 1676557d2bdcSMaxim Levitsky 1677557d2bdcSMaxim Levitsky static int 1678557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, 1679557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1680557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1681557d2bdcSMaxim Levitsky void *opaque, 1682557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1683557d2bdcSMaxim Levitsky bool force, 1684557d2bdcSMaxim Levitsky Error **errp) 1685557d2bdcSMaxim Levitsky { 1686557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1687557d2bdcSMaxim Levitsky g_autofree uint8_t *tmpkey = NULL; 1688557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1689557d2bdcSMaxim Levitsky 169016110c8bSMarkus Armbruster if (opts_luks->new_secret) { 1691557d2bdcSMaxim Levitsky error_setg(errp, 1692557d2bdcSMaxim Levitsky "'new-secret' must not be given when erasing keyslots"); 1693557d2bdcSMaxim Levitsky return -1; 1694557d2bdcSMaxim Levitsky } 1695557d2bdcSMaxim Levitsky if (opts_luks->has_iter_time) { 1696557d2bdcSMaxim Levitsky error_setg(errp, 1697557d2bdcSMaxim Levitsky "'iter-time' must not be given when erasing keyslots"); 1698557d2bdcSMaxim Levitsky return -1; 1699557d2bdcSMaxim Levitsky } 170016110c8bSMarkus Armbruster if (opts_luks->secret) { 1701557d2bdcSMaxim Levitsky error_setg(errp, 1702557d2bdcSMaxim Levitsky "'secret' must not be given when erasing keyslots"); 1703557d2bdcSMaxim Levitsky return -1; 1704557d2bdcSMaxim Levitsky } 1705557d2bdcSMaxim Levitsky 1706557d2bdcSMaxim Levitsky /* Load the old password if given */ 170716110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1708557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, 1709557d2bdcSMaxim Levitsky errp); 1710557d2bdcSMaxim Levitsky if (!old_password) { 1711557d2bdcSMaxim Levitsky return -1; 1712557d2bdcSMaxim Levitsky } 1713557d2bdcSMaxim Levitsky 1714557d2bdcSMaxim Levitsky /* 1715557d2bdcSMaxim Levitsky * Allocate a temporary key buffer that we will need when 1716557d2bdcSMaxim Levitsky * checking if slot matches the given old password 1717557d2bdcSMaxim Levitsky */ 1718557d2bdcSMaxim Levitsky tmpkey = g_new0(uint8_t, luks->header.master_key_len); 1719557d2bdcSMaxim Levitsky } 1720557d2bdcSMaxim Levitsky 1721557d2bdcSMaxim Levitsky /* Erase an explicitly given keyslot */ 1722557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1723557d2bdcSMaxim Levitsky int keyslot = opts_luks->keyslot; 1724557d2bdcSMaxim Levitsky 1725557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1726557d2bdcSMaxim Levitsky error_setg(errp, 1727557d2bdcSMaxim Levitsky "Invalid keyslot %i specified, must be between 0 and %i", 1728557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1729557d2bdcSMaxim Levitsky return -1; 1730557d2bdcSMaxim Levitsky } 1731557d2bdcSMaxim Levitsky 173216110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1733557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1734557d2bdcSMaxim Levitsky keyslot, 1735557d2bdcSMaxim Levitsky old_password, 1736557d2bdcSMaxim Levitsky tmpkey, 1737557d2bdcSMaxim Levitsky readfunc, 1738557d2bdcSMaxim Levitsky opaque, 1739557d2bdcSMaxim Levitsky errp); 1740557d2bdcSMaxim Levitsky if (rv == -1) { 1741557d2bdcSMaxim Levitsky return -1; 1742557d2bdcSMaxim Levitsky } else if (rv == 0) { 1743557d2bdcSMaxim Levitsky error_setg(errp, 1744557d2bdcSMaxim Levitsky "Given keyslot %i doesn't contain the given " 1745557d2bdcSMaxim Levitsky "old password for erase operation", 1746557d2bdcSMaxim Levitsky keyslot); 1747557d2bdcSMaxim Levitsky return -1; 1748557d2bdcSMaxim Levitsky } 1749557d2bdcSMaxim Levitsky } 1750557d2bdcSMaxim Levitsky 1751557d2bdcSMaxim Levitsky if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { 1752557d2bdcSMaxim Levitsky error_setg(errp, 1753557d2bdcSMaxim Levitsky "Given keyslot %i is already erased (inactive) ", 1754557d2bdcSMaxim Levitsky keyslot); 1755557d2bdcSMaxim Levitsky return -1; 1756557d2bdcSMaxim Levitsky } 1757557d2bdcSMaxim Levitsky 1758557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { 1759557d2bdcSMaxim Levitsky error_setg(errp, 1760557d2bdcSMaxim Levitsky "Attempt to erase the only active keyslot %i " 1761557d2bdcSMaxim Levitsky "which will erase all the data in the image " 1762557d2bdcSMaxim Levitsky "irreversibly - refusing operation", 1763557d2bdcSMaxim Levitsky keyslot); 1764557d2bdcSMaxim Levitsky return -1; 1765557d2bdcSMaxim Levitsky } 1766557d2bdcSMaxim Levitsky 1767557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, keyslot, 1768557d2bdcSMaxim Levitsky writefunc, opaque, errp)) { 1769557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %i", keyslot); 1770557d2bdcSMaxim Levitsky return -1; 1771557d2bdcSMaxim Levitsky } 1772557d2bdcSMaxim Levitsky 1773557d2bdcSMaxim Levitsky /* Erase all keyslots that match the given old password */ 177416110c8bSMarkus Armbruster } else if (opts_luks->old_secret) { 1775557d2bdcSMaxim Levitsky 1776557d2bdcSMaxim Levitsky unsigned long slots_to_erase_bitmap = 0; 1777557d2bdcSMaxim Levitsky size_t i; 1778557d2bdcSMaxim Levitsky int slot_count; 1779557d2bdcSMaxim Levitsky 1780557d2bdcSMaxim Levitsky assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= 1781557d2bdcSMaxim Levitsky sizeof(slots_to_erase_bitmap) * 8); 1782557d2bdcSMaxim Levitsky 1783557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1784557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1785557d2bdcSMaxim Levitsky i, 1786557d2bdcSMaxim Levitsky old_password, 1787557d2bdcSMaxim Levitsky tmpkey, 1788557d2bdcSMaxim Levitsky readfunc, 1789557d2bdcSMaxim Levitsky opaque, 1790557d2bdcSMaxim Levitsky errp); 1791557d2bdcSMaxim Levitsky if (rv == -1) { 1792557d2bdcSMaxim Levitsky return -1; 1793557d2bdcSMaxim Levitsky } else if (rv == 1) { 1794557d2bdcSMaxim Levitsky bitmap_set(&slots_to_erase_bitmap, i, 1); 1795557d2bdcSMaxim Levitsky } 1796557d2bdcSMaxim Levitsky } 1797557d2bdcSMaxim Levitsky 1798557d2bdcSMaxim Levitsky slot_count = bitmap_count_one(&slots_to_erase_bitmap, 1799557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1800557d2bdcSMaxim Levitsky if (slot_count == 0) { 1801557d2bdcSMaxim Levitsky error_setg(errp, 1802557d2bdcSMaxim Levitsky "No keyslots match given (old) password for erase operation"); 1803557d2bdcSMaxim Levitsky return -1; 1804557d2bdcSMaxim Levitsky } 1805557d2bdcSMaxim Levitsky 1806557d2bdcSMaxim Levitsky if (!force && 1807557d2bdcSMaxim Levitsky slot_count == qcrypto_block_luks_count_active_slots(luks)) { 1808557d2bdcSMaxim Levitsky error_setg(errp, 1809557d2bdcSMaxim Levitsky "All the active keyslots match the (old) password that " 1810557d2bdcSMaxim Levitsky "was given and erasing them will erase all the data in " 1811557d2bdcSMaxim Levitsky "the image irreversibly - refusing operation"); 1812557d2bdcSMaxim Levitsky return -1; 1813557d2bdcSMaxim Levitsky } 1814557d2bdcSMaxim Levitsky 1815557d2bdcSMaxim Levitsky /* Now apply the update */ 1816557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1817557d2bdcSMaxim Levitsky if (!test_bit(i, &slots_to_erase_bitmap)) { 1818557d2bdcSMaxim Levitsky continue; 1819557d2bdcSMaxim Levitsky } 1820557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, i, writefunc, 1821557d2bdcSMaxim Levitsky opaque, errp)) { 1822557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %zu", i); 1823557d2bdcSMaxim Levitsky return -1; 1824557d2bdcSMaxim Levitsky } 1825557d2bdcSMaxim Levitsky } 1826557d2bdcSMaxim Levitsky } else { 1827557d2bdcSMaxim Levitsky error_setg(errp, 1828557d2bdcSMaxim Levitsky "To erase keyslot(s), either explicit keyslot index " 1829557d2bdcSMaxim Levitsky "or the password currently contained in them must be given"); 1830557d2bdcSMaxim Levitsky return -1; 1831557d2bdcSMaxim Levitsky } 1832557d2bdcSMaxim Levitsky return 0; 1833557d2bdcSMaxim Levitsky } 1834557d2bdcSMaxim Levitsky 1835557d2bdcSMaxim Levitsky static int 1836557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block, 1837557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1838557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1839557d2bdcSMaxim Levitsky void *opaque, 1840557d2bdcSMaxim Levitsky QCryptoBlockAmendOptions *options, 1841557d2bdcSMaxim Levitsky bool force, 1842557d2bdcSMaxim Levitsky Error **errp) 1843557d2bdcSMaxim Levitsky { 1844557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; 1845557d2bdcSMaxim Levitsky 1846557d2bdcSMaxim Levitsky switch (opts_luks->state) { 1847557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: 1848557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_add_keyslot(block, readfunc, 1849557d2bdcSMaxim Levitsky writefunc, opaque, 1850557d2bdcSMaxim Levitsky opts_luks, force, errp); 1851557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: 1852557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, 1853557d2bdcSMaxim Levitsky writefunc, opaque, 1854557d2bdcSMaxim Levitsky opts_luks, force, errp); 1855557d2bdcSMaxim Levitsky default: 1856557d2bdcSMaxim Levitsky g_assert_not_reached(); 1857557d2bdcSMaxim Levitsky } 1858557d2bdcSMaxim Levitsky } 18593e308f20SDaniel P. Berrange 186040c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 186140c85028SDaniel P. Berrange QCryptoBlockInfo *info, 186240c85028SDaniel P. Berrange Error **errp) 186340c85028SDaniel P. Berrange { 186440c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 186540c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 1866c3033fd3SEric Blake QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots; 186740c85028SDaniel P. Berrange size_t i; 186840c85028SDaniel P. Berrange 186940c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 187040c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 187140c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 187240c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 187340c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 187440c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 187540c85028SDaniel P. Berrange } 187640c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 187740c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 187840c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 187940c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 188040c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 188140c85028SDaniel P. Berrange 188240c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1883c3033fd3SEric Blake slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 188440c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 188540c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1886f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 188740c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 188840c85028SDaniel P. Berrange if (slot->active) { 188940c85028SDaniel P. Berrange slot->has_iters = true; 189040c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 189140c85028SDaniel P. Berrange slot->has_stripes = true; 189240c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 189340c85028SDaniel P. Berrange } 189440c85028SDaniel P. Berrange 1895c3033fd3SEric Blake QAPI_LIST_APPEND(tail, slot); 189640c85028SDaniel P. Berrange } 189740c85028SDaniel P. Berrange 189840c85028SDaniel P. Berrange return 0; 189940c85028SDaniel P. Berrange } 190040c85028SDaniel P. Berrange 190140c85028SDaniel P. Berrange 19023e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 19033e308f20SDaniel P. Berrange { 1904557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1905557d2bdcSMaxim Levitsky if (luks) { 1906557d2bdcSMaxim Levitsky g_free(luks->secret); 1907557d2bdcSMaxim Levitsky g_free(luks); 1908557d2bdcSMaxim Levitsky } 19093e308f20SDaniel P. Berrange } 19103e308f20SDaniel P. Berrange 19113e308f20SDaniel P. Berrange 19123e308f20SDaniel P. Berrange static int 19133e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 19144609742aSDaniel P. Berrange uint64_t offset, 19153e308f20SDaniel P. Berrange uint8_t *buf, 19163e308f20SDaniel P. Berrange size_t len, 19173e308f20SDaniel P. Berrange Error **errp) 19183e308f20SDaniel P. Berrange { 19194609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19204609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19210f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 19223e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19234609742aSDaniel P. Berrange offset, buf, len, errp); 19243e308f20SDaniel P. Berrange } 19253e308f20SDaniel P. Berrange 19263e308f20SDaniel P. Berrange 19273e308f20SDaniel P. Berrange static int 19283e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 19294609742aSDaniel P. Berrange uint64_t offset, 19303e308f20SDaniel P. Berrange uint8_t *buf, 19313e308f20SDaniel P. Berrange size_t len, 19323e308f20SDaniel P. Berrange Error **errp) 19333e308f20SDaniel P. Berrange { 19344609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19354609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19360f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 19373e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19384609742aSDaniel P. Berrange offset, buf, len, errp); 19393e308f20SDaniel P. Berrange } 19403e308f20SDaniel P. Berrange 19413e308f20SDaniel P. Berrange 19423e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 19433e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 19443e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 1945557d2bdcSMaxim Levitsky .amend = qcrypto_block_luks_amend_options, 194640c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 19473e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 19483e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 19493e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 19503e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 19513e308f20SDaniel P. Berrange }; 1952