13e308f20SDaniel P. Berrange /* 23e308f20SDaniel P. Berrange * QEMU Crypto block device encryption LUKS format 33e308f20SDaniel P. Berrange * 43e308f20SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 53e308f20SDaniel P. Berrange * 63e308f20SDaniel P. Berrange * This library is free software; you can redistribute it and/or 73e308f20SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 83e308f20SDaniel P. Berrange * License as published by the Free Software Foundation; either 9b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 103e308f20SDaniel P. Berrange * 113e308f20SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 123e308f20SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 133e308f20SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143e308f20SDaniel P. Berrange * Lesser General Public License for more details. 153e308f20SDaniel P. Berrange * 163e308f20SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 173e308f20SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 183e308f20SDaniel P. Berrange * 193e308f20SDaniel P. Berrange */ 203e308f20SDaniel P. Berrange 213e308f20SDaniel P. Berrange #include "qemu/osdep.h" 22da34e65cSMarkus Armbruster #include "qapi/error.h" 2358369e22SPaolo Bonzini #include "qemu/bswap.h" 243e308f20SDaniel P. Berrange 25986bc8deSMichael S. Tsirkin #include "block-luks.h" 2636445aceSDaniel P. Berrangé #include "block-luks-priv.h" 273e308f20SDaniel P. Berrange 283e308f20SDaniel P. Berrange #include "crypto/hash.h" 293e308f20SDaniel P. Berrange #include "crypto/afsplit.h" 303e308f20SDaniel P. Berrange #include "crypto/pbkdf.h" 313e308f20SDaniel P. Berrange #include "crypto/secret.h" 323e308f20SDaniel P. Berrange #include "crypto/random.h" 332ef950f9SFam Zheng #include "qemu/uuid.h" 343e308f20SDaniel P. Berrange 35557d2bdcSMaxim Levitsky #include "qemu/bitmap.h" 363e308f20SDaniel P. Berrange 373e308f20SDaniel P. Berrange /* 383e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is 393e308f20SDaniel P. Berrange * 403e308f20SDaniel P. Berrange * docs/on-disk-format.pdf 413e308f20SDaniel P. Berrange * 423e308f20SDaniel P. Berrange * in 'cryptsetup' package source code 433e308f20SDaniel P. Berrange * 443e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated 453e308f20SDaniel P. Berrange * Oct 16, 2011. 463e308f20SDaniel P. Berrange */ 473e308f20SDaniel P. Berrange 483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS; 493e308f20SDaniel P. Berrange 503e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap; 513e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap { 523e308f20SDaniel P. Berrange const char *name; 533e308f20SDaniel P. Berrange int id; 543e308f20SDaniel P. Berrange }; 553e308f20SDaniel P. Berrange 563e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap; 573e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap { 583e308f20SDaniel P. Berrange uint32_t key_bytes; 593e308f20SDaniel P. Berrange int id; 603e308f20SDaniel P. Berrange }; 613e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap; 623e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap { 633e308f20SDaniel P. Berrange const char *name; 643e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes; 653e308f20SDaniel P. Berrange }; 663e308f20SDaniel P. Berrange 673e308f20SDaniel P. Berrange 683e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 693e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = { 703e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 }, 713e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 }, 723e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 }, 733e308f20SDaniel P. Berrange { 0, 0 }, 743e308f20SDaniel P. Berrange }; 753e308f20SDaniel P. Berrange 763e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 773e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = { 783e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 }, 793e308f20SDaniel P. Berrange { 0, 0 }, 803e308f20SDaniel P. Berrange }; 813e308f20SDaniel P. Berrange 823e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 833e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = { 843e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 }, 853e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 }, 863e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 }, 873e308f20SDaniel P. Berrange { 0, 0 }, 883e308f20SDaniel P. Berrange }; 893e308f20SDaniel P. Berrange 903e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 913e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = { 923e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 }, 933e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 }, 943e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 }, 953e308f20SDaniel P. Berrange { 0, 0 }, 963e308f20SDaniel P. Berrange }; 973e308f20SDaniel P. Berrange 9852ed9f45SHyman Huang #ifdef CONFIG_CRYPTO_SM4 9952ed9f45SHyman Huang static const QCryptoBlockLUKSCipherSizeMap 10052ed9f45SHyman Huang qcrypto_block_luks_cipher_size_map_sm4[] = { 10152ed9f45SHyman Huang { 16, QCRYPTO_CIPHER_ALG_SM4}, 10252ed9f45SHyman Huang { 0, 0 }, 10352ed9f45SHyman Huang }; 10452ed9f45SHyman Huang #endif 10552ed9f45SHyman Huang 1063e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap 1073e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = { 1083e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes }, 1093e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, 1103e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, 1113e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, 11252ed9f45SHyman Huang #ifdef CONFIG_CRYPTO_SM4 11352ed9f45SHyman Huang { "sm4", qcrypto_block_luks_cipher_size_map_sm4}, 11452ed9f45SHyman Huang #endif 1153e308f20SDaniel P. Berrange }; 1163e308f20SDaniel P. Berrange 1173e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); 1183e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592); 1193e308f20SDaniel P. Berrange 1203e308f20SDaniel P. Berrange 1213e308f20SDaniel P. Berrange struct QCryptoBlockLUKS { 1223e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header; 12340c85028SDaniel P. Berrange 1249d80e59dSMaxim Levitsky /* Main encryption algorithm used for encryption*/ 12540c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 1269d80e59dSMaxim Levitsky 1279d80e59dSMaxim Levitsky /* Mode of encryption for the selected encryption algorithm */ 12840c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 1299d80e59dSMaxim Levitsky 1309d80e59dSMaxim Levitsky /* Initialization vector generation algorithm */ 13140c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 1329d80e59dSMaxim Levitsky 1339d80e59dSMaxim Levitsky /* Hash algorithm used for IV generation*/ 13440c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 1359d80e59dSMaxim Levitsky 1369d80e59dSMaxim Levitsky /* 1379d80e59dSMaxim Levitsky * Encryption algorithm used for IV generation. 1389d80e59dSMaxim Levitsky * Usually the same as main encryption algorithm 1399d80e59dSMaxim Levitsky */ 1409d80e59dSMaxim Levitsky QCryptoCipherAlgorithm ivgen_cipher_alg; 1419d80e59dSMaxim Levitsky 1429d80e59dSMaxim Levitsky /* Hash algorithm used in pbkdf2 function */ 14340c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 144557d2bdcSMaxim Levitsky 145557d2bdcSMaxim Levitsky /* Name of the secret that was used to open the image */ 146557d2bdcSMaxim Levitsky char *secret; 1473e308f20SDaniel P. Berrange }; 1483e308f20SDaniel P. Berrange 1493e308f20SDaniel P. Berrange 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 4719ad5c4e7SHyman Huang qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, 4729ad5c4e7SHyman Huang unsigned int flags, 4739ad5c4e7SHyman Huang Error **errp) 4749fa9c1c2SMaxim Levitsky { 475befdba9eSMaxim Levitsky size_t i, j; 476befdba9eSMaxim Levitsky 477befdba9eSMaxim Levitsky unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 478befdba9eSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 4799ad5c4e7SHyman Huang bool detached = flags & QCRYPTO_BLOCK_OPEN_DETACHED; 480befdba9eSMaxim Levitsky 4819fa9c1c2SMaxim Levitsky if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 4829fa9c1c2SMaxim Levitsky QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 4839fa9c1c2SMaxim Levitsky error_setg(errp, "Volume is not in LUKS format"); 4849fa9c1c2SMaxim Levitsky return -1; 4859fa9c1c2SMaxim Levitsky } 4869fa9c1c2SMaxim Levitsky 4879fa9c1c2SMaxim Levitsky if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 4889fa9c1c2SMaxim Levitsky error_setg(errp, "LUKS version %" PRIu32 " is not supported", 4899fa9c1c2SMaxim Levitsky luks->header.version); 4909fa9c1c2SMaxim Levitsky return -1; 4919fa9c1c2SMaxim Levitsky } 492befdba9eSMaxim Levitsky 493c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_name, '\0', 494c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_name))) { 495c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher name is not NUL terminated"); 496c1d8634cSDaniel P. Berrangé return -1; 497c1d8634cSDaniel P. Berrangé } 498c1d8634cSDaniel P. Berrangé 499c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_mode, '\0', 500c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_mode))) { 501c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher mode is not NUL terminated"); 502c1d8634cSDaniel P. Berrangé return -1; 503c1d8634cSDaniel P. Berrangé } 504c1d8634cSDaniel P. Berrangé 505c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.hash_spec, '\0', 506c1d8634cSDaniel P. Berrangé sizeof(luks->header.hash_spec))) { 507c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header hash spec is not NUL terminated"); 508c1d8634cSDaniel P. Berrangé return -1; 509c1d8634cSDaniel P. Berrangé } 510c1d8634cSDaniel P. Berrangé 5119ad5c4e7SHyman Huang if (!detached && luks->header.payload_offset_sector < 512d233fbc3SDaniel P. Berrangé DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 513d233fbc3SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 514d233fbc3SDaniel P. Berrangé error_setg(errp, "LUKS payload is overlapping with the header"); 515d233fbc3SDaniel P. Berrangé return -1; 516d233fbc3SDaniel P. Berrangé } 517d233fbc3SDaniel P. Berrangé 518b57151acSDaniel P. Berrangé if (luks->header.master_key_iterations == 0) { 519b57151acSDaniel P. Berrangé error_setg(errp, "LUKS key iteration count is zero"); 520b57151acSDaniel P. Berrangé return -1; 521b57151acSDaniel P. Berrangé } 522b57151acSDaniel P. Berrangé 523befdba9eSMaxim Levitsky /* Check all keyslots for corruption */ 524befdba9eSMaxim Levitsky for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) { 525befdba9eSMaxim Levitsky 526befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i]; 527befdba9eSMaxim Levitsky unsigned int start1 = slot1->key_offset_sector; 528befdba9eSMaxim Levitsky unsigned int len1 = 529befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 530befdba9eSMaxim Levitsky header_sectors, 531befdba9eSMaxim Levitsky slot1->stripes); 532befdba9eSMaxim Levitsky 533f1195961SDaniel P. Berrangé if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) { 534f1195961SDaniel P. Berrangé error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)", 535f1195961SDaniel P. Berrangé i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES); 536befdba9eSMaxim Levitsky return -1; 537befdba9eSMaxim Levitsky } 538befdba9eSMaxim Levitsky 539befdba9eSMaxim Levitsky if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED && 540befdba9eSMaxim Levitsky slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 541befdba9eSMaxim Levitsky error_setg(errp, 542befdba9eSMaxim Levitsky "Keyslot %zu state (active/disable) is corrupted", i); 543befdba9eSMaxim Levitsky return -1; 544befdba9eSMaxim Levitsky } 545befdba9eSMaxim Levitsky 546b57151acSDaniel P. Berrangé if (slot1->active == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED && 547b57151acSDaniel P. Berrangé slot1->iterations == 0) { 548b57151acSDaniel P. Berrangé error_setg(errp, "Keyslot %zu iteration count is zero", i); 549b57151acSDaniel P. Berrangé return -1; 550b57151acSDaniel P. Berrangé } 551b57151acSDaniel P. Berrangé 552c5f69628SDaniel P. Berrangé if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 55393569c37SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 55493569c37SDaniel P. Berrangé error_setg(errp, 55593569c37SDaniel P. Berrangé "Keyslot %zu is overlapping with the LUKS header", 55693569c37SDaniel P. Berrangé i); 55793569c37SDaniel P. Berrangé return -1; 55893569c37SDaniel P. Berrangé } 55993569c37SDaniel P. Berrangé 5609ad5c4e7SHyman Huang if (!detached && start1 + len1 > luks->header.payload_offset_sector) { 561befdba9eSMaxim Levitsky error_setg(errp, 562befdba9eSMaxim Levitsky "Keyslot %zu is overlapping with the encrypted payload", 563befdba9eSMaxim Levitsky i); 564befdba9eSMaxim Levitsky return -1; 565befdba9eSMaxim Levitsky } 566befdba9eSMaxim Levitsky 567befdba9eSMaxim Levitsky for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) { 568befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j]; 569befdba9eSMaxim Levitsky unsigned int start2 = slot2->key_offset_sector; 570befdba9eSMaxim Levitsky unsigned int len2 = 571befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 572befdba9eSMaxim Levitsky header_sectors, 573befdba9eSMaxim Levitsky slot2->stripes); 574befdba9eSMaxim Levitsky 575befdba9eSMaxim Levitsky if (start1 + len1 > start2 && start2 + len2 > start1) { 576befdba9eSMaxim Levitsky error_setg(errp, 577befdba9eSMaxim Levitsky "Keyslots %zu and %zu are overlapping in the header", 578befdba9eSMaxim Levitsky i, j); 579befdba9eSMaxim Levitsky return -1; 580befdba9eSMaxim Levitsky } 581befdba9eSMaxim Levitsky } 582befdba9eSMaxim Levitsky 583befdba9eSMaxim Levitsky } 5849fa9c1c2SMaxim Levitsky return 0; 5859fa9c1c2SMaxim Levitsky } 5869fa9c1c2SMaxim Levitsky 5879fa9c1c2SMaxim Levitsky /* 5889fa9c1c2SMaxim Levitsky * Parses the crypto parameters that are stored in the LUKS header 5899fa9c1c2SMaxim Levitsky */ 5909fa9c1c2SMaxim Levitsky 5919fa9c1c2SMaxim Levitsky static int 5929fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp) 5939fa9c1c2SMaxim Levitsky { 5949fa9c1c2SMaxim Levitsky g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode); 5959fa9c1c2SMaxim Levitsky char *ivgen_name, *ivhash_name; 5969fa9c1c2SMaxim Levitsky Error *local_err = NULL; 5979fa9c1c2SMaxim Levitsky 5989fa9c1c2SMaxim Levitsky /* 5999fa9c1c2SMaxim Levitsky * The cipher_mode header contains a string that we have 6009fa9c1c2SMaxim Levitsky * to further parse, of the format 6019fa9c1c2SMaxim Levitsky * 6029fa9c1c2SMaxim Levitsky * <cipher-mode>-<iv-generator>[:<iv-hash>] 6039fa9c1c2SMaxim Levitsky * 6049fa9c1c2SMaxim Levitsky * eg cbc-essiv:sha256, cbc-plain64 6059fa9c1c2SMaxim Levitsky */ 6069fa9c1c2SMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 6079fa9c1c2SMaxim Levitsky if (!ivgen_name) { 6086c198932SDaniel P. Berrangé error_setg(errp, "Unexpected cipher mode string format '%s'", 6099fa9c1c2SMaxim Levitsky luks->header.cipher_mode); 6109fa9c1c2SMaxim Levitsky return -1; 6119fa9c1c2SMaxim Levitsky } 6129fa9c1c2SMaxim Levitsky *ivgen_name = '\0'; 6139fa9c1c2SMaxim Levitsky ivgen_name++; 6149fa9c1c2SMaxim Levitsky 6159fa9c1c2SMaxim Levitsky ivhash_name = strchr(ivgen_name, ':'); 6169fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6179fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = 0; 6189fa9c1c2SMaxim Levitsky } else { 6199fa9c1c2SMaxim Levitsky *ivhash_name = '\0'; 6209fa9c1c2SMaxim Levitsky ivhash_name++; 6219fa9c1c2SMaxim Levitsky 6229fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 6239fa9c1c2SMaxim Levitsky &local_err); 6249fa9c1c2SMaxim Levitsky if (local_err) { 6259fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6269fa9c1c2SMaxim Levitsky return -1; 6279fa9c1c2SMaxim Levitsky } 6289fa9c1c2SMaxim Levitsky } 6299fa9c1c2SMaxim Levitsky 6309fa9c1c2SMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 6319fa9c1c2SMaxim Levitsky &local_err); 6329fa9c1c2SMaxim Levitsky if (local_err) { 6339fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6349fa9c1c2SMaxim Levitsky return -1; 6359fa9c1c2SMaxim Levitsky } 6369fa9c1c2SMaxim Levitsky 6379fa9c1c2SMaxim Levitsky luks->cipher_alg = 6389fa9c1c2SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 6399fa9c1c2SMaxim Levitsky luks->cipher_mode, 6409fa9c1c2SMaxim Levitsky luks->header.master_key_len, 6419fa9c1c2SMaxim Levitsky &local_err); 6429fa9c1c2SMaxim Levitsky if (local_err) { 6439fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6449fa9c1c2SMaxim Levitsky return -1; 6459fa9c1c2SMaxim Levitsky } 6469fa9c1c2SMaxim Levitsky 6479fa9c1c2SMaxim Levitsky luks->hash_alg = 6489fa9c1c2SMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 6499fa9c1c2SMaxim Levitsky &local_err); 6509fa9c1c2SMaxim Levitsky if (local_err) { 6519fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6529fa9c1c2SMaxim Levitsky return -1; 6539fa9c1c2SMaxim Levitsky } 6549fa9c1c2SMaxim Levitsky 6559fa9c1c2SMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 6569fa9c1c2SMaxim Levitsky &local_err); 6579fa9c1c2SMaxim Levitsky if (local_err) { 6589fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6599fa9c1c2SMaxim Levitsky return -1; 6609fa9c1c2SMaxim Levitsky } 6619fa9c1c2SMaxim Levitsky 6629fa9c1c2SMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 6639fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6649fa9c1c2SMaxim Levitsky error_setg(errp, "Missing IV generator hash specification"); 6659fa9c1c2SMaxim Levitsky return -1; 6669fa9c1c2SMaxim Levitsky } 6679fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = 6689fa9c1c2SMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 6699fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg, 6709fa9c1c2SMaxim Levitsky &local_err); 6719fa9c1c2SMaxim Levitsky if (local_err) { 6729fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6739fa9c1c2SMaxim Levitsky return -1; 6749fa9c1c2SMaxim Levitsky } 6759fa9c1c2SMaxim Levitsky } else { 6769fa9c1c2SMaxim Levitsky 6779fa9c1c2SMaxim Levitsky /* 6789fa9c1c2SMaxim Levitsky * Note we parsed the ivhash_name earlier in the cipher_mode 6799fa9c1c2SMaxim Levitsky * spec string even with plain/plain64 ivgens, but we 6809fa9c1c2SMaxim Levitsky * will ignore it, since it is irrelevant for these ivgens. 6819fa9c1c2SMaxim Levitsky * This is for compat with dm-crypt which will silently 6829fa9c1c2SMaxim Levitsky * ignore hash names with these ivgens rather than report 6839fa9c1c2SMaxim Levitsky * an error about the invalid usage 6849fa9c1c2SMaxim Levitsky */ 6859fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 6869fa9c1c2SMaxim Levitsky } 6879fa9c1c2SMaxim Levitsky return 0; 6889fa9c1c2SMaxim Levitsky } 6899fa9c1c2SMaxim Levitsky 6909fa9c1c2SMaxim Levitsky /* 6913994a7c9SMaxim Levitsky * Given a key slot, user password, and the master key, 6923994a7c9SMaxim Levitsky * will store the encrypted master key there, and update the 6933994a7c9SMaxim Levitsky * in-memory header. User must then write the in-memory header 6943994a7c9SMaxim Levitsky * 6953994a7c9SMaxim Levitsky * Returns: 6963994a7c9SMaxim Levitsky * 0 if the keyslot was written successfully 6973994a7c9SMaxim Levitsky * with the provided password 6983994a7c9SMaxim Levitsky * -1 if a fatal error occurred while storing the key 6993994a7c9SMaxim Levitsky */ 7003994a7c9SMaxim Levitsky static int 7013994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block, 7023994a7c9SMaxim Levitsky unsigned int slot_idx, 7033994a7c9SMaxim Levitsky const char *password, 7043994a7c9SMaxim Levitsky uint8_t *masterkey, 7053994a7c9SMaxim Levitsky uint64_t iter_time, 7063994a7c9SMaxim Levitsky QCryptoBlockWriteFunc writefunc, 7073994a7c9SMaxim Levitsky void *opaque, 7083994a7c9SMaxim Levitsky Error **errp) 7093994a7c9SMaxim Levitsky { 7103994a7c9SMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 711557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 7123994a7c9SMaxim Levitsky g_autofree uint8_t *splitkey = NULL; 7133994a7c9SMaxim Levitsky size_t splitkeylen; 7143994a7c9SMaxim Levitsky g_autofree uint8_t *slotkey = NULL; 7153994a7c9SMaxim Levitsky g_autoptr(QCryptoCipher) cipher = NULL; 7163994a7c9SMaxim Levitsky g_autoptr(QCryptoIVGen) ivgen = NULL; 7173994a7c9SMaxim Levitsky Error *local_err = NULL; 7183994a7c9SMaxim Levitsky uint64_t iters; 7193994a7c9SMaxim Levitsky int ret = -1; 7203994a7c9SMaxim Levitsky 721557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 722557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 72355a01cabSAkihiko Odaki splitkeylen = luks->header.master_key_len * slot->stripes; 72455a01cabSAkihiko Odaki 7253994a7c9SMaxim Levitsky if (qcrypto_random_bytes(slot->salt, 7263994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7273994a7c9SMaxim Levitsky errp) < 0) { 7283994a7c9SMaxim Levitsky goto cleanup; 7293994a7c9SMaxim Levitsky } 7303994a7c9SMaxim Levitsky 7313994a7c9SMaxim Levitsky /* 7323994a7c9SMaxim Levitsky * Determine how many iterations are required to 7333994a7c9SMaxim Levitsky * hash the user password while consuming 1 second of compute 7343994a7c9SMaxim Levitsky * time 7353994a7c9SMaxim Levitsky */ 7363994a7c9SMaxim Levitsky iters = qcrypto_pbkdf2_count_iters(luks->hash_alg, 7373994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7383994a7c9SMaxim Levitsky slot->salt, 7393994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7403994a7c9SMaxim Levitsky luks->header.master_key_len, 7413994a7c9SMaxim Levitsky &local_err); 7423994a7c9SMaxim Levitsky if (local_err) { 7433994a7c9SMaxim Levitsky error_propagate(errp, local_err); 7443994a7c9SMaxim Levitsky goto cleanup; 7453994a7c9SMaxim Levitsky } 7463994a7c9SMaxim Levitsky 7473994a7c9SMaxim Levitsky if (iters > (ULLONG_MAX / iter_time)) { 7483994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7493994a7c9SMaxim Levitsky "PBKDF iterations %llu too large to scale", 7503994a7c9SMaxim Levitsky (unsigned long long)iters); 7513994a7c9SMaxim Levitsky goto cleanup; 7523994a7c9SMaxim Levitsky } 7533994a7c9SMaxim Levitsky 7543994a7c9SMaxim Levitsky /* iter_time was in millis, but count_iters reported for secs */ 7553994a7c9SMaxim Levitsky iters = iters * iter_time / 1000; 7563994a7c9SMaxim Levitsky 7573994a7c9SMaxim Levitsky if (iters > UINT32_MAX) { 7583994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7593994a7c9SMaxim Levitsky "PBKDF iterations %llu larger than %u", 7603994a7c9SMaxim Levitsky (unsigned long long)iters, UINT32_MAX); 7613994a7c9SMaxim Levitsky goto cleanup; 7623994a7c9SMaxim Levitsky } 7633994a7c9SMaxim Levitsky 7643994a7c9SMaxim Levitsky slot->iterations = 7653994a7c9SMaxim Levitsky MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 7663994a7c9SMaxim Levitsky 7673994a7c9SMaxim Levitsky 7683994a7c9SMaxim Levitsky /* 7693994a7c9SMaxim Levitsky * Generate a key that we'll use to encrypt the master 7703994a7c9SMaxim Levitsky * key, from the user's password 7713994a7c9SMaxim Levitsky */ 7723994a7c9SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 7733994a7c9SMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 7743994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7753994a7c9SMaxim Levitsky slot->salt, 7763994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7773994a7c9SMaxim Levitsky slot->iterations, 7783994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7793994a7c9SMaxim Levitsky errp) < 0) { 7803994a7c9SMaxim Levitsky goto cleanup; 7813994a7c9SMaxim Levitsky } 7823994a7c9SMaxim Levitsky 7833994a7c9SMaxim Levitsky 7843994a7c9SMaxim Levitsky /* 7853994a7c9SMaxim Levitsky * Setup the encryption objects needed to encrypt the 7863994a7c9SMaxim Levitsky * master key material 7873994a7c9SMaxim Levitsky */ 7883994a7c9SMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 7893994a7c9SMaxim Levitsky luks->cipher_mode, 7903994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7913994a7c9SMaxim Levitsky errp); 7923994a7c9SMaxim Levitsky if (!cipher) { 7933994a7c9SMaxim Levitsky goto cleanup; 7943994a7c9SMaxim Levitsky } 7953994a7c9SMaxim Levitsky 7963994a7c9SMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 7973994a7c9SMaxim Levitsky luks->ivgen_cipher_alg, 7983994a7c9SMaxim Levitsky luks->ivgen_hash_alg, 7993994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 8003994a7c9SMaxim Levitsky errp); 8013994a7c9SMaxim Levitsky if (!ivgen) { 8023994a7c9SMaxim Levitsky goto cleanup; 8033994a7c9SMaxim Levitsky } 8043994a7c9SMaxim Levitsky 8053994a7c9SMaxim Levitsky /* 8063994a7c9SMaxim Levitsky * Before storing the master key, we need to vastly 8073994a7c9SMaxim Levitsky * increase its size, as protection against forensic 8083994a7c9SMaxim Levitsky * disk data recovery 8093994a7c9SMaxim Levitsky */ 8103994a7c9SMaxim Levitsky splitkey = g_new0(uint8_t, splitkeylen); 8113994a7c9SMaxim Levitsky 8123994a7c9SMaxim Levitsky if (qcrypto_afsplit_encode(luks->hash_alg, 8133994a7c9SMaxim Levitsky luks->header.master_key_len, 8143994a7c9SMaxim Levitsky slot->stripes, 8153994a7c9SMaxim Levitsky masterkey, 8163994a7c9SMaxim Levitsky splitkey, 8173994a7c9SMaxim Levitsky errp) < 0) { 8183994a7c9SMaxim Levitsky goto cleanup; 8193994a7c9SMaxim Levitsky } 8203994a7c9SMaxim Levitsky 8213994a7c9SMaxim Levitsky /* 8223994a7c9SMaxim Levitsky * Now we encrypt the split master key with the key generated 8233994a7c9SMaxim Levitsky * from the user's password, before storing it 8243994a7c9SMaxim Levitsky */ 8253994a7c9SMaxim Levitsky if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 8263994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8273994a7c9SMaxim Levitsky 0, 8283994a7c9SMaxim Levitsky splitkey, 8293994a7c9SMaxim Levitsky splitkeylen, 8303994a7c9SMaxim Levitsky errp) < 0) { 8313994a7c9SMaxim Levitsky goto cleanup; 8323994a7c9SMaxim Levitsky } 8333994a7c9SMaxim Levitsky 8343994a7c9SMaxim Levitsky /* Write out the slot's master key material. */ 8353994a7c9SMaxim Levitsky if (writefunc(block, 8363994a7c9SMaxim Levitsky slot->key_offset_sector * 8373994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8383994a7c9SMaxim Levitsky splitkey, splitkeylen, 8393994a7c9SMaxim Levitsky opaque, 840757dda54SAlberto Faria errp) < 0) { 8413994a7c9SMaxim Levitsky goto cleanup; 8423994a7c9SMaxim Levitsky } 8433994a7c9SMaxim Levitsky 8443994a7c9SMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 8453994a7c9SMaxim Levitsky 8463994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) { 8473994a7c9SMaxim Levitsky goto cleanup; 8483994a7c9SMaxim Levitsky } 8493994a7c9SMaxim Levitsky 8503994a7c9SMaxim Levitsky ret = 0; 8513994a7c9SMaxim Levitsky 8523994a7c9SMaxim Levitsky cleanup: 8533994a7c9SMaxim Levitsky if (slotkey) { 8543994a7c9SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 8553994a7c9SMaxim Levitsky } 8563994a7c9SMaxim Levitsky if (splitkey) { 8573994a7c9SMaxim Levitsky memset(splitkey, 0, splitkeylen); 8583994a7c9SMaxim Levitsky } 8593994a7c9SMaxim Levitsky return ret; 8603994a7c9SMaxim Levitsky } 8613994a7c9SMaxim Levitsky 8623994a7c9SMaxim Levitsky /* 8633e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 8643e308f20SDaniel P. Berrange * the master encryption key from the key slot. 8653e308f20SDaniel P. Berrange * 8663e308f20SDaniel P. Berrange * Returns: 8673e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 8683e308f20SDaniel P. Berrange * with the provided password 8693e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 8703e308f20SDaniel P. Berrange * with the provided password 8713e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 8723e308f20SDaniel P. Berrange */ 8733e308f20SDaniel P. Berrange static int 8743e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 8757e60a6f5SMaxim Levitsky size_t slot_idx, 8763e308f20SDaniel P. Berrange const char *password, 8773e308f20SDaniel P. Berrange uint8_t *masterkey, 8783e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 8793e308f20SDaniel P. Berrange void *opaque, 8803e308f20SDaniel P. Berrange Error **errp) 8813e308f20SDaniel P. Berrange { 8823e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 883557d2bdcSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot; 88457b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 8853e308f20SDaniel P. Berrange size_t splitkeylen; 88657b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 887757dda54SAlberto Faria int rv; 88857b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 8893e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 89057b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 8913e308f20SDaniel P. Berrange size_t niv; 8923e308f20SDaniel P. Berrange 893557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 894557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 8953e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 8963e308f20SDaniel P. Berrange return 0; 8973e308f20SDaniel P. Berrange } 8983e308f20SDaniel P. Berrange 8991ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 9003e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 9011ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 9023e308f20SDaniel P. Berrange 9033e308f20SDaniel P. Berrange /* 9043e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 9053e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 9063e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 9073e308f20SDaniel P. Berrange * the key is correct and validate the results of 9083e308f20SDaniel P. Berrange * decryption later. 9093e308f20SDaniel P. Berrange */ 9109d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 9113e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 9123e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 9133e308f20SDaniel P. Berrange slot->iterations, 9141ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 9153e308f20SDaniel P. Berrange errp) < 0) { 91657b9f113SDaniel P. Berrangé return -1; 9173e308f20SDaniel P. Berrange } 9183e308f20SDaniel P. Berrange 9193e308f20SDaniel P. Berrange /* 9203e308f20SDaniel P. Berrange * We need to read the master key material from the 9213e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 9223e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 9233e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 9243e308f20SDaniel P. Berrange * then encrypted. 9253e308f20SDaniel P. Berrange */ 9263e308f20SDaniel P. Berrange rv = readfunc(block, 927f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9283e308f20SDaniel P. Berrange splitkey, splitkeylen, 929e4a3507eSDaniel P. Berrange opaque, 93037509233SFam Zheng errp); 9313e308f20SDaniel P. Berrange if (rv < 0) { 93257b9f113SDaniel P. Berrangé return -1; 9333e308f20SDaniel P. Berrange } 9343e308f20SDaniel P. Berrange 9353e308f20SDaniel P. Berrange 9363e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 9373e308f20SDaniel P. Berrange * the split master key material */ 9389d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 9399d80e59dSMaxim Levitsky luks->cipher_mode, 9409d80e59dSMaxim Levitsky possiblekey, 9419d80e59dSMaxim Levitsky luks->header.master_key_len, 9423e308f20SDaniel P. Berrange errp); 9433e308f20SDaniel P. Berrange if (!cipher) { 94457b9f113SDaniel P. Berrangé return -1; 9453e308f20SDaniel P. Berrange } 9463e308f20SDaniel P. Berrange 9479d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 9489d80e59dSMaxim Levitsky luks->cipher_mode); 9499d80e59dSMaxim Levitsky 9509d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 9519d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 9529d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 9539d80e59dSMaxim Levitsky possiblekey, 9549d80e59dSMaxim Levitsky luks->header.master_key_len, 9553e308f20SDaniel P. Berrange errp); 9563e308f20SDaniel P. Berrange if (!ivgen) { 95757b9f113SDaniel P. Berrangé return -1; 9583e308f20SDaniel P. Berrange } 9593e308f20SDaniel P. Berrange 9603e308f20SDaniel P. Berrange 9613e308f20SDaniel P. Berrange /* 9623e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 9633e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 9643e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 9653e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 9663e308f20SDaniel P. Berrange * key crosses a sector boundary. 9673e308f20SDaniel P. Berrange */ 9680270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 9693e308f20SDaniel P. Berrange niv, 9703e308f20SDaniel P. Berrange ivgen, 9713e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9723e308f20SDaniel P. Berrange 0, 9733e308f20SDaniel P. Berrange splitkey, 9743e308f20SDaniel P. Berrange splitkeylen, 9753e308f20SDaniel P. Berrange errp) < 0) { 97657b9f113SDaniel P. Berrangé return -1; 9773e308f20SDaniel P. Berrange } 9783e308f20SDaniel P. Berrange 9793e308f20SDaniel P. Berrange /* 9803e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 9813e308f20SDaniel P. Berrange * it back together to get the actual master key. 9823e308f20SDaniel P. Berrange */ 9839d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 9841ddd52e4SMaxim Levitsky luks->header.master_key_len, 9853e308f20SDaniel P. Berrange slot->stripes, 9863e308f20SDaniel P. Berrange splitkey, 9873e308f20SDaniel P. Berrange masterkey, 9883e308f20SDaniel P. Berrange errp) < 0) { 98957b9f113SDaniel P. Berrangé return -1; 9903e308f20SDaniel P. Berrange } 9913e308f20SDaniel P. Berrange 9923e308f20SDaniel P. Berrange 9933e308f20SDaniel P. Berrange /* 9943e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 9953e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 9963e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 9973e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 9983e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 9993e308f20SDaniel P. Berrange * header 10003e308f20SDaniel P. Berrange */ 10019d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 10021ddd52e4SMaxim Levitsky masterkey, 10031ddd52e4SMaxim Levitsky luks->header.master_key_len, 10043e308f20SDaniel P. Berrange luks->header.master_key_salt, 10053e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 10063e308f20SDaniel P. Berrange luks->header.master_key_iterations, 10071ddd52e4SMaxim Levitsky keydigest, 10081ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 10093e308f20SDaniel P. Berrange errp) < 0) { 101057b9f113SDaniel P. Berrangé return -1; 10113e308f20SDaniel P. Berrange } 10123e308f20SDaniel P. Berrange 10133e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 10143e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 10153e308f20SDaniel P. Berrange /* Success, we got the right master key */ 101657b9f113SDaniel P. Berrangé return 1; 10173e308f20SDaniel P. Berrange } 10183e308f20SDaniel P. Berrange 10193e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 10203e308f20SDaniel P. Berrange * tell caller to try another slot */ 102157b9f113SDaniel P. Berrangé return 0; 10223e308f20SDaniel P. Berrange } 10233e308f20SDaniel P. Berrange 10243e308f20SDaniel P. Berrange 10253e308f20SDaniel P. Berrange /* 10263e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 10273e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 10283e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 10293e308f20SDaniel P. Berrange * 10303e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 10313e308f20SDaniel P. Berrange */ 10323e308f20SDaniel P. Berrange static int 10333e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 10343e308f20SDaniel P. Berrange const char *password, 10351ddd52e4SMaxim Levitsky uint8_t *masterkey, 10363e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 10373e308f20SDaniel P. Berrange void *opaque, 10383e308f20SDaniel P. Berrange Error **errp) 10393e308f20SDaniel P. Berrange { 10403e308f20SDaniel P. Berrange size_t i; 10413e308f20SDaniel P. Berrange int rv; 10423e308f20SDaniel P. Berrange 10433e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10443e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 10457e60a6f5SMaxim Levitsky i, 10463e308f20SDaniel P. Berrange password, 10471ddd52e4SMaxim Levitsky masterkey, 10483e308f20SDaniel P. Berrange readfunc, 10493e308f20SDaniel P. Berrange opaque, 10503e308f20SDaniel P. Berrange errp); 10513e308f20SDaniel P. Berrange if (rv < 0) { 10523e308f20SDaniel P. Berrange goto error; 10533e308f20SDaniel P. Berrange } 10543e308f20SDaniel P. Berrange if (rv == 1) { 10553e308f20SDaniel P. Berrange return 0; 10563e308f20SDaniel P. Berrange } 10573e308f20SDaniel P. Berrange } 10583e308f20SDaniel P. Berrange 10593e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 10603e308f20SDaniel P. Berrange error: 10613e308f20SDaniel P. Berrange return -1; 10623e308f20SDaniel P. Berrange } 10633e308f20SDaniel P. Berrange 1064557d2bdcSMaxim Levitsky /* 1065557d2bdcSMaxim Levitsky * Returns true if a slot i is marked as active 1066557d2bdcSMaxim Levitsky * (contains encrypted copy of the master key) 1067557d2bdcSMaxim Levitsky */ 1068557d2bdcSMaxim Levitsky static bool 1069557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, 1070557d2bdcSMaxim Levitsky unsigned int slot_idx) 1071557d2bdcSMaxim Levitsky { 1072557d2bdcSMaxim Levitsky uint32_t val; 1073557d2bdcSMaxim Levitsky 1074557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1075557d2bdcSMaxim Levitsky val = luks->header.key_slots[slot_idx].active; 1076557d2bdcSMaxim Levitsky return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1077557d2bdcSMaxim Levitsky } 1078557d2bdcSMaxim Levitsky 1079557d2bdcSMaxim Levitsky /* 1080557d2bdcSMaxim Levitsky * Returns the number of slots that are marked as active 1081557d2bdcSMaxim Levitsky * (slots that contain encrypted copy of the master key) 1082557d2bdcSMaxim Levitsky */ 1083557d2bdcSMaxim Levitsky static unsigned int 1084557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) 1085557d2bdcSMaxim Levitsky { 1086557d2bdcSMaxim Levitsky size_t i = 0; 1087557d2bdcSMaxim Levitsky unsigned int ret = 0; 1088557d2bdcSMaxim Levitsky 1089557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1090557d2bdcSMaxim Levitsky if (qcrypto_block_luks_slot_active(luks, i)) { 1091557d2bdcSMaxim Levitsky ret++; 1092557d2bdcSMaxim Levitsky } 1093557d2bdcSMaxim Levitsky } 1094557d2bdcSMaxim Levitsky return ret; 1095557d2bdcSMaxim Levitsky } 1096557d2bdcSMaxim Levitsky 1097557d2bdcSMaxim Levitsky /* 1098557d2bdcSMaxim Levitsky * Finds first key slot which is not active 1099557d2bdcSMaxim Levitsky * Returns the key slot index, or -1 if it doesn't exist 1100557d2bdcSMaxim Levitsky */ 1101557d2bdcSMaxim Levitsky static int 1102557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) 1103557d2bdcSMaxim Levitsky { 1104557d2bdcSMaxim Levitsky size_t i; 1105557d2bdcSMaxim Levitsky 1106557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1107557d2bdcSMaxim Levitsky if (!qcrypto_block_luks_slot_active(luks, i)) { 1108557d2bdcSMaxim Levitsky return i; 1109557d2bdcSMaxim Levitsky } 1110557d2bdcSMaxim Levitsky } 1111557d2bdcSMaxim Levitsky return -1; 1112557d2bdcSMaxim Levitsky } 1113557d2bdcSMaxim Levitsky 1114557d2bdcSMaxim Levitsky /* 1115557d2bdcSMaxim Levitsky * Erases an keyslot given its index 1116557d2bdcSMaxim Levitsky * Returns: 1117557d2bdcSMaxim Levitsky * 0 if the keyslot was erased successfully 1118557d2bdcSMaxim Levitsky * -1 if a error occurred while erasing the keyslot 1119557d2bdcSMaxim Levitsky * 1120557d2bdcSMaxim Levitsky */ 1121557d2bdcSMaxim Levitsky static int 1122557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block, 1123557d2bdcSMaxim Levitsky unsigned int slot_idx, 1124557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1125557d2bdcSMaxim Levitsky void *opaque, 1126557d2bdcSMaxim Levitsky Error **errp) 1127557d2bdcSMaxim Levitsky { 1128557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1129557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 1130557d2bdcSMaxim Levitsky g_autofree uint8_t *garbagesplitkey = NULL; 1131557d2bdcSMaxim Levitsky size_t splitkeylen; 1132557d2bdcSMaxim Levitsky size_t i; 1133557d2bdcSMaxim Levitsky Error *local_err = NULL; 1134557d2bdcSMaxim Levitsky int ret; 1135557d2bdcSMaxim Levitsky 1136557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1137557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 1138557d2bdcSMaxim Levitsky 1139557d2bdcSMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 1140557d2bdcSMaxim Levitsky assert(splitkeylen > 0); 1141557d2bdcSMaxim Levitsky 1142557d2bdcSMaxim Levitsky garbagesplitkey = g_new0(uint8_t, splitkeylen); 1143557d2bdcSMaxim Levitsky 1144557d2bdcSMaxim Levitsky /* Reset the key slot header */ 1145557d2bdcSMaxim Levitsky memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); 1146557d2bdcSMaxim Levitsky slot->iterations = 0; 1147557d2bdcSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 1148557d2bdcSMaxim Levitsky 1149557d2bdcSMaxim Levitsky ret = qcrypto_block_luks_store_header(block, writefunc, 1150557d2bdcSMaxim Levitsky opaque, &local_err); 1151557d2bdcSMaxim Levitsky 1152557d2bdcSMaxim Levitsky if (ret < 0) { 1153557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1154557d2bdcSMaxim Levitsky } 1155557d2bdcSMaxim Levitsky /* 1156557d2bdcSMaxim Levitsky * Now try to erase the key material, even if the header 1157557d2bdcSMaxim Levitsky * update failed 1158557d2bdcSMaxim Levitsky */ 1159557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { 1160557d2bdcSMaxim Levitsky if (qcrypto_random_bytes(garbagesplitkey, 1161557d2bdcSMaxim Levitsky splitkeylen, &local_err) < 0) { 1162557d2bdcSMaxim Levitsky /* 1163557d2bdcSMaxim Levitsky * If we failed to get the random data, still write 1164557d2bdcSMaxim Levitsky * at least zeros to the key slot at least once 1165557d2bdcSMaxim Levitsky */ 1166557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1167557d2bdcSMaxim Levitsky 1168557d2bdcSMaxim Levitsky if (i > 0) { 1169557d2bdcSMaxim Levitsky return -1; 1170557d2bdcSMaxim Levitsky } 1171557d2bdcSMaxim Levitsky } 1172557d2bdcSMaxim Levitsky if (writefunc(block, 1173557d2bdcSMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 1174557d2bdcSMaxim Levitsky garbagesplitkey, 1175557d2bdcSMaxim Levitsky splitkeylen, 1176557d2bdcSMaxim Levitsky opaque, 1177757dda54SAlberto Faria &local_err) < 0) { 1178557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1179557d2bdcSMaxim Levitsky return -1; 1180557d2bdcSMaxim Levitsky } 1181557d2bdcSMaxim Levitsky } 1182557d2bdcSMaxim Levitsky return ret; 1183557d2bdcSMaxim Levitsky } 11843e308f20SDaniel P. Berrange 11853e308f20SDaniel P. Berrange static int 11863e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 11873e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 11881cd9a787SDaniel P. Berrange const char *optprefix, 11893e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 11903e308f20SDaniel P. Berrange void *opaque, 11913e308f20SDaniel P. Berrange unsigned int flags, 1192c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 11933e308f20SDaniel P. Berrange Error **errp) 11943e308f20SDaniel P. Berrange { 11959d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 119657b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 119757b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 11983e308f20SDaniel P. Berrange 11993e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12003e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 12011cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 12021cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 12033e308f20SDaniel P. Berrange return -1; 12043e308f20SDaniel P. Berrange } 12053e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 12063e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 12073e308f20SDaniel P. Berrange if (!password) { 12083e308f20SDaniel P. Berrange return -1; 12093e308f20SDaniel P. Berrange } 12103e308f20SDaniel P. Berrange } 12113e308f20SDaniel P. Berrange 12123e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 12133e308f20SDaniel P. Berrange block->opaque = luks; 1214557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 12153e308f20SDaniel P. Berrange 1216dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 12173e308f20SDaniel P. Berrange goto fail; 12183e308f20SDaniel P. Berrange } 12193e308f20SDaniel P. Berrange 12209ad5c4e7SHyman Huang if (qcrypto_block_luks_check_header(luks, flags, errp) < 0) { 12213e308f20SDaniel P. Berrange goto fail; 12223e308f20SDaniel P. Berrange } 12233e308f20SDaniel P. Berrange 12249fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_parse_header(luks, errp) < 0) { 12253e308f20SDaniel P. Berrange goto fail; 12263e308f20SDaniel P. Berrange } 12273e308f20SDaniel P. Berrange 12283e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12293e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 12303e308f20SDaniel P. Berrange * and unlock the master key from that slot. 12313e308f20SDaniel P. Berrange */ 12321ddd52e4SMaxim Levitsky 12331ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 12341ddd52e4SMaxim Levitsky 12353e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 12363e308f20SDaniel P. Berrange password, 12371ddd52e4SMaxim Levitsky masterkey, 12383e308f20SDaniel P. Berrange readfunc, opaque, 12393e308f20SDaniel P. Berrange errp) < 0) { 12403e308f20SDaniel P. Berrange goto fail; 12413e308f20SDaniel P. Berrange } 12423e308f20SDaniel P. Berrange 12433e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 12443e308f20SDaniel P. Berrange * block device payload decryption objects 12453e308f20SDaniel P. Berrange */ 12469d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 12479d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 12489d80e59dSMaxim Levitsky luks->cipher_mode); 12499d80e59dSMaxim Levitsky 12509d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 12519d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 12529d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 12531ddd52e4SMaxim Levitsky masterkey, 12541ddd52e4SMaxim Levitsky luks->header.master_key_len, 12553e308f20SDaniel P. Berrange errp); 12563e308f20SDaniel P. Berrange if (!block->ivgen) { 12573e308f20SDaniel P. Berrange goto fail; 12583e308f20SDaniel P. Berrange } 12593e308f20SDaniel P. Berrange 126061dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 12619d80e59dSMaxim Levitsky luks->cipher_alg, 12629d80e59dSMaxim Levitsky luks->cipher_mode, 12631ddd52e4SMaxim Levitsky masterkey, 12641ddd52e4SMaxim Levitsky luks->header.master_key_len, 12651ddd52e4SMaxim Levitsky n_threads, 126661dd8a9aSMaxim Levitsky errp) < 0) { 12673e308f20SDaniel P. Berrange goto fail; 12683e308f20SDaniel P. Berrange } 12693e308f20SDaniel P. Berrange } 12703e308f20SDaniel P. Berrange 1271850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1272f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1273850f49deSDaniel P. Berrange block->sector_size; 12743e308f20SDaniel P. Berrange 12753e308f20SDaniel P. Berrange return 0; 12763e308f20SDaniel P. Berrange 12773e308f20SDaniel P. Berrange fail: 1278c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 12793e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 1280557d2bdcSMaxim Levitsky g_free(luks->secret); 12813e308f20SDaniel P. Berrange g_free(luks); 128261dd8a9aSMaxim Levitsky return -1; 12833e308f20SDaniel P. Berrange } 12843e308f20SDaniel P. Berrange 12853e308f20SDaniel P. Berrange 12862ef950f9SFam Zheng static void 12872ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 12883e308f20SDaniel P. Berrange { 12892ef950f9SFam Zheng QemuUUID uuid; 12902ef950f9SFam Zheng qemu_uuid_generate(&uuid); 12912ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 12923e308f20SDaniel P. Berrange } 12933e308f20SDaniel P. Berrange 12943e308f20SDaniel P. Berrange static int 12953e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 12963e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 12971cd9a787SDaniel P. Berrange const char *optprefix, 12983e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 12993e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 13003e308f20SDaniel P. Berrange void *opaque, 13013e308f20SDaniel P. Berrange Error **errp) 13023e308f20SDaniel P. Berrange { 13033e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 13043e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 13053e308f20SDaniel P. Berrange Error *local_err = NULL; 130657b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 1307bd56a55aSMaxim Levitsky size_t header_sectors; 1308bd56a55aSMaxim Levitsky size_t split_key_sectors; 13093e308f20SDaniel P. Berrange size_t i; 131057b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 13113e308f20SDaniel P. Berrange const char *cipher_alg; 13123e308f20SDaniel P. Berrange const char *cipher_mode; 13133e308f20SDaniel P. Berrange const char *ivgen_alg; 13143e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 13153e308f20SDaniel P. Berrange const char *hash_alg; 131657b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 131759b060beSDaniel P. Berrange uint64_t iters; 1318*d74523a3SHyman Huang uint64_t detached_header_size; 13193e308f20SDaniel P. Berrange 13203e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 13213bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 1322557d2bdcSMaxim Levitsky luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 13233bd18890SDaniel P. Berrange } 13243e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 13253e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 13263e308f20SDaniel P. Berrange } 13273e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 13283e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 13293e308f20SDaniel P. Berrange } 13303e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 13313e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 13323e308f20SDaniel P. Berrange } 13333e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 13343e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 13353e308f20SDaniel P. Berrange } 13368b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 13378b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 13388b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 13398b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 13408b7cdba3SDaniel P. Berrange } 13418b7cdba3SDaniel P. Berrange } 13429d80e59dSMaxim Levitsky 13439d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 13449d80e59dSMaxim Levitsky block->opaque = luks; 13459d80e59dSMaxim Levitsky 13469d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 13479d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 13489d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 13499d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 13509d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 13519d80e59dSMaxim Levitsky 13529d80e59dSMaxim Levitsky 13538b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 13548b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 13558b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 13563e308f20SDaniel P. Berrange 13573e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 13581cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 13591cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 13609d80e59dSMaxim Levitsky goto error; 13613e308f20SDaniel P. Berrange } 1362557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 1363557d2bdcSMaxim Levitsky 13643e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 13653e308f20SDaniel P. Berrange if (!password) { 13669d80e59dSMaxim Levitsky goto error; 13673e308f20SDaniel P. Berrange } 13683e308f20SDaniel P. Berrange 13693e308f20SDaniel P. Berrange 13703e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 13713e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 13723e308f20SDaniel P. Berrange 13733e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 13743e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 13753e308f20SDaniel P. Berrange * it out to disk 13763e308f20SDaniel P. Berrange */ 13773e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 13782ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 13793e308f20SDaniel P. Berrange 13803e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 13813e308f20SDaniel P. Berrange errp); 13823e308f20SDaniel P. Berrange if (!cipher_alg) { 13833e308f20SDaniel P. Berrange goto error; 13843e308f20SDaniel P. Berrange } 13853e308f20SDaniel P. Berrange 1386977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 1387977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 13883e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 1389977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 13903e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 13913e308f20SDaniel P. Berrange ivgen_hash_alg); 13923e308f20SDaniel P. Berrange } else { 13933e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 13943e308f20SDaniel P. Berrange } 1395977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 13963e308f20SDaniel P. Berrange 13973e308f20SDaniel P. Berrange 13983e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 13993e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 14003e308f20SDaniel P. Berrange cipher_alg); 14013e308f20SDaniel P. Berrange goto error; 14023e308f20SDaniel P. Berrange } 14033e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 14043e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 14053e308f20SDaniel P. Berrange cipher_mode_spec); 14063e308f20SDaniel P. Berrange goto error; 14073e308f20SDaniel P. Berrange } 14083e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 14093e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 14103e308f20SDaniel P. Berrange hash_alg); 14113e308f20SDaniel P. Berrange goto error; 14123e308f20SDaniel P. Berrange } 14133e308f20SDaniel P. Berrange 14143e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 14159d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 14169d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 14173e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 14183e308f20SDaniel P. Berrange &local_err); 14193e308f20SDaniel P. Berrange if (local_err) { 14203e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14213e308f20SDaniel P. Berrange goto error; 14223e308f20SDaniel P. Berrange } 14233e308f20SDaniel P. Berrange } else { 14249d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 14253e308f20SDaniel P. Berrange } 14263e308f20SDaniel P. Berrange 14273e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 14283e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 14293e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 14303e308f20SDaniel P. Berrange 1431f0d3c362SMaxim Levitsky luks->header.master_key_len = 1432f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 1433f0d3c362SMaxim Levitsky 14343e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 1435f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 14363e308f20SDaniel P. Berrange } 14373e308f20SDaniel P. Berrange 14383e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 14393e308f20SDaniel P. Berrange * with PBKDF later 14403e308f20SDaniel P. Berrange */ 14413e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 14423e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 14433e308f20SDaniel P. Berrange errp) < 0) { 14443e308f20SDaniel P. Berrange goto error; 14453e308f20SDaniel P. Berrange } 14463e308f20SDaniel P. Berrange 14473e308f20SDaniel P. Berrange /* Generate random master key */ 1448f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 14493e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 1450f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 14513e308f20SDaniel P. Berrange goto error; 14523e308f20SDaniel P. Berrange } 14533e308f20SDaniel P. Berrange 14543e308f20SDaniel P. Berrange 14553e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1456c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1457c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1458f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 14593e308f20SDaniel P. Berrange goto error; 14603e308f20SDaniel P. Berrange } 14613e308f20SDaniel P. Berrange 14623e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 14633e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 14643e308f20SDaniel P. Berrange luks_opts.cipher_mode); 14653e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 14669d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 14673e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1468f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14693e308f20SDaniel P. Berrange errp); 14703e308f20SDaniel P. Berrange 14713e308f20SDaniel P. Berrange if (!block->ivgen) { 14723e308f20SDaniel P. Berrange goto error; 14733e308f20SDaniel P. Berrange } 14743e308f20SDaniel P. Berrange 14753e308f20SDaniel P. Berrange 14763e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 14773e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 14783e308f20SDaniel P. Berrange */ 147959b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1480f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14813e308f20SDaniel P. Berrange luks->header.master_key_salt, 14823e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1483e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 14843e308f20SDaniel P. Berrange &local_err); 14853e308f20SDaniel P. Berrange if (local_err) { 14863e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14873e308f20SDaniel P. Berrange goto error; 14883e308f20SDaniel P. Berrange } 14893e308f20SDaniel P. Berrange 14903bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 14913bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 14923bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 14933bd18890SDaniel P. Berrange (unsigned long long)iters); 14943bd18890SDaniel P. Berrange goto error; 14953bd18890SDaniel P. Berrange } 14963bd18890SDaniel P. Berrange 14973bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 14983bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 14993bd18890SDaniel P. Berrange 15003e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 15013e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 15023e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 15033e308f20SDaniel P. Berrange * in total time to check all keys */ 150459b060beSDaniel P. Berrange iters /= 8; 150559b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 150659b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 150759b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 150859b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 150959b060beSDaniel P. Berrange goto error; 151059b060beSDaniel P. Berrange } 151159b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 151259b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 15133e308f20SDaniel P. Berrange 15143e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 15153e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 15163e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 15173e308f20SDaniel P. Berrange * valid master key 15183e308f20SDaniel P. Berrange */ 15193e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1520f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 15213e308f20SDaniel P. Berrange luks->header.master_key_salt, 15223e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 15233e308f20SDaniel P. Berrange luks->header.master_key_iterations, 15243e308f20SDaniel P. Berrange luks->header.master_key_digest, 15253e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 15263e308f20SDaniel P. Berrange errp) < 0) { 15273e308f20SDaniel P. Berrange goto error; 15283e308f20SDaniel P. Berrange } 15293e308f20SDaniel P. Berrange 1530bd56a55aSMaxim Levitsky /* start with the sector that follows the header*/ 1531bd56a55aSMaxim Levitsky header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 1532bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 15333e308f20SDaniel P. Berrange 1534bd56a55aSMaxim Levitsky split_key_sectors = 1535bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 1536bd56a55aSMaxim Levitsky header_sectors, 1537bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_STRIPES); 1538bd56a55aSMaxim Levitsky 15393e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1540bd56a55aSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i]; 1541bd56a55aSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 15423e308f20SDaniel P. Berrange 1543bd56a55aSMaxim Levitsky slot->key_offset_sector = header_sectors + i * split_key_sectors; 1544bd56a55aSMaxim Levitsky slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 15453e308f20SDaniel P. Berrange } 15463e308f20SDaniel P. Berrange 1547*d74523a3SHyman Huang if (block->detached_header) { 1548*d74523a3SHyman Huang /* 1549*d74523a3SHyman Huang * For a detached LUKS header image, set the payload_offset_sector 1550*d74523a3SHyman Huang * to 0 to specify the starting point for read/write 1551*d74523a3SHyman Huang */ 1552*d74523a3SHyman Huang luks->header.payload_offset_sector = 0; 1553*d74523a3SHyman Huang } else { 1554*d74523a3SHyman Huang /* 1555*d74523a3SHyman Huang * The total size of the LUKS headers is the partition header + key 15563e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 15573e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 1558*d74523a3SHyman Huang * to the nearest sector 1559*d74523a3SHyman Huang */ 1560bd56a55aSMaxim Levitsky luks->header.payload_offset_sector = header_sectors + 1561bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors; 1562*d74523a3SHyman Huang } 15633e308f20SDaniel P. Berrange 1564850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1565f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1566850f49deSDaniel P. Berrange block->sector_size; 1567*d74523a3SHyman Huang detached_header_size = 1568*d74523a3SHyman Huang (header_sectors + QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * 1569*d74523a3SHyman Huang split_key_sectors) * block->sector_size; 15703e308f20SDaniel P. Berrange 15713e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1572*d74523a3SHyman Huang initfunc(block, detached_header_size, opaque, &local_err); 15733e308f20SDaniel P. Berrange if (local_err) { 15743e308f20SDaniel P. Berrange error_propagate(errp, local_err); 15753e308f20SDaniel P. Berrange goto error; 15763e308f20SDaniel P. Berrange } 15773e308f20SDaniel P. Berrange 15783e308f20SDaniel P. Berrange 15793994a7c9SMaxim Levitsky /* populate the slot 0 with the password encrypted master key*/ 15803994a7c9SMaxim Levitsky /* This will also store the header */ 15813994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_key(block, 15823994a7c9SMaxim Levitsky 0, 15833994a7c9SMaxim Levitsky password, 15843994a7c9SMaxim Levitsky masterkey, 15853994a7c9SMaxim Levitsky luks_opts.iter_time, 15863994a7c9SMaxim Levitsky writefunc, 1587e4a3507eSDaniel P. Berrange opaque, 15883994a7c9SMaxim Levitsky errp) < 0) { 15893e308f20SDaniel P. Berrange goto error; 15903e308f20SDaniel P. Berrange } 15913e308f20SDaniel P. Berrange 1592f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15933e308f20SDaniel P. Berrange 15943e308f20SDaniel P. Berrange return 0; 15953e308f20SDaniel P. Berrange 15963e308f20SDaniel P. Berrange error: 15973e308f20SDaniel P. Berrange if (masterkey) { 1598f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15993e308f20SDaniel P. Berrange } 16003e308f20SDaniel P. Berrange 1601c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1602b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1603b640adcaSVladimir Sementsov-Ogievskiy 1604557d2bdcSMaxim Levitsky g_free(luks->secret); 16053e308f20SDaniel P. Berrange g_free(luks); 16063e308f20SDaniel P. Berrange return -1; 16073e308f20SDaniel P. Berrange } 16083e308f20SDaniel P. Berrange 1609557d2bdcSMaxim Levitsky static int 1610557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, 1611557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1612557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1613557d2bdcSMaxim Levitsky void *opaque, 1614557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1615557d2bdcSMaxim Levitsky bool force, 1616557d2bdcSMaxim Levitsky Error **errp) 1617557d2bdcSMaxim Levitsky { 1618557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1619557d2bdcSMaxim Levitsky uint64_t iter_time = opts_luks->has_iter_time ? 1620557d2bdcSMaxim Levitsky opts_luks->iter_time : 1621557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1622557d2bdcSMaxim Levitsky int keyslot; 1623557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1624557d2bdcSMaxim Levitsky g_autofree char *new_password = NULL; 1625557d2bdcSMaxim Levitsky g_autofree uint8_t *master_key = NULL; 1626557d2bdcSMaxim Levitsky 162716110c8bSMarkus Armbruster char *secret = opts_luks->secret ?: luks->secret; 1628557d2bdcSMaxim Levitsky 162916110c8bSMarkus Armbruster if (!opts_luks->new_secret) { 1630557d2bdcSMaxim Levitsky error_setg(errp, "'new-secret' is required to activate a keyslot"); 1631557d2bdcSMaxim Levitsky return -1; 1632557d2bdcSMaxim Levitsky } 163316110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1634557d2bdcSMaxim Levitsky error_setg(errp, 1635557d2bdcSMaxim Levitsky "'old-secret' must not be given when activating keyslots"); 1636557d2bdcSMaxim Levitsky return -1; 1637557d2bdcSMaxim Levitsky } 1638557d2bdcSMaxim Levitsky 1639557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1640557d2bdcSMaxim Levitsky keyslot = opts_luks->keyslot; 1641557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1642557d2bdcSMaxim Levitsky error_setg(errp, 1643557d2bdcSMaxim Levitsky "Invalid keyslot %u specified, must be between 0 and %u", 1644557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1645557d2bdcSMaxim Levitsky return -1; 1646557d2bdcSMaxim Levitsky } 1647557d2bdcSMaxim Levitsky } else { 1648557d2bdcSMaxim Levitsky keyslot = qcrypto_block_luks_find_free_keyslot(luks); 1649557d2bdcSMaxim Levitsky if (keyslot == -1) { 1650557d2bdcSMaxim Levitsky error_setg(errp, 1651557d2bdcSMaxim Levitsky "Can't add a keyslot - all keyslots are in use"); 1652557d2bdcSMaxim Levitsky return -1; 1653557d2bdcSMaxim Levitsky } 1654557d2bdcSMaxim Levitsky } 1655557d2bdcSMaxim Levitsky 1656557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { 1657557d2bdcSMaxim Levitsky error_setg(errp, 1658557d2bdcSMaxim Levitsky "Refusing to overwrite active keyslot %i - " 1659557d2bdcSMaxim Levitsky "please erase it first", 1660557d2bdcSMaxim Levitsky keyslot); 1661557d2bdcSMaxim Levitsky return -1; 1662557d2bdcSMaxim Levitsky } 1663557d2bdcSMaxim Levitsky 1664557d2bdcSMaxim Levitsky /* Locate the password that will be used to retrieve the master key */ 1665557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(secret, errp); 1666557d2bdcSMaxim Levitsky if (!old_password) { 1667557d2bdcSMaxim Levitsky return -1; 1668557d2bdcSMaxim Levitsky } 1669557d2bdcSMaxim Levitsky 1670557d2bdcSMaxim Levitsky /* Retrieve the master key */ 1671557d2bdcSMaxim Levitsky master_key = g_new0(uint8_t, luks->header.master_key_len); 1672557d2bdcSMaxim Levitsky 1673557d2bdcSMaxim Levitsky if (qcrypto_block_luks_find_key(block, old_password, master_key, 1674557d2bdcSMaxim Levitsky readfunc, opaque, errp) < 0) { 1675557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to retrieve the master key"); 1676557d2bdcSMaxim Levitsky return -1; 1677557d2bdcSMaxim Levitsky } 1678557d2bdcSMaxim Levitsky 1679557d2bdcSMaxim Levitsky /* Locate the new password*/ 1680557d2bdcSMaxim Levitsky new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); 1681557d2bdcSMaxim Levitsky if (!new_password) { 1682557d2bdcSMaxim Levitsky return -1; 1683557d2bdcSMaxim Levitsky } 1684557d2bdcSMaxim Levitsky 1685557d2bdcSMaxim Levitsky /* Now set the new keyslots */ 1686557d2bdcSMaxim Levitsky if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, 1687557d2bdcSMaxim Levitsky iter_time, writefunc, opaque, errp)) { 1688557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to write to keyslot %i", keyslot); 1689557d2bdcSMaxim Levitsky return -1; 1690557d2bdcSMaxim Levitsky } 1691557d2bdcSMaxim Levitsky return 0; 1692557d2bdcSMaxim Levitsky } 1693557d2bdcSMaxim Levitsky 1694557d2bdcSMaxim Levitsky static int 1695557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, 1696557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1697557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1698557d2bdcSMaxim Levitsky void *opaque, 1699557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1700557d2bdcSMaxim Levitsky bool force, 1701557d2bdcSMaxim Levitsky Error **errp) 1702557d2bdcSMaxim Levitsky { 1703557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1704557d2bdcSMaxim Levitsky g_autofree uint8_t *tmpkey = NULL; 1705557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1706557d2bdcSMaxim Levitsky 170716110c8bSMarkus Armbruster if (opts_luks->new_secret) { 1708557d2bdcSMaxim Levitsky error_setg(errp, 1709557d2bdcSMaxim Levitsky "'new-secret' must not be given when erasing keyslots"); 1710557d2bdcSMaxim Levitsky return -1; 1711557d2bdcSMaxim Levitsky } 1712557d2bdcSMaxim Levitsky if (opts_luks->has_iter_time) { 1713557d2bdcSMaxim Levitsky error_setg(errp, 1714557d2bdcSMaxim Levitsky "'iter-time' must not be given when erasing keyslots"); 1715557d2bdcSMaxim Levitsky return -1; 1716557d2bdcSMaxim Levitsky } 171716110c8bSMarkus Armbruster if (opts_luks->secret) { 1718557d2bdcSMaxim Levitsky error_setg(errp, 1719557d2bdcSMaxim Levitsky "'secret' must not be given when erasing keyslots"); 1720557d2bdcSMaxim Levitsky return -1; 1721557d2bdcSMaxim Levitsky } 1722557d2bdcSMaxim Levitsky 1723557d2bdcSMaxim Levitsky /* Load the old password if given */ 172416110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1725557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, 1726557d2bdcSMaxim Levitsky errp); 1727557d2bdcSMaxim Levitsky if (!old_password) { 1728557d2bdcSMaxim Levitsky return -1; 1729557d2bdcSMaxim Levitsky } 1730557d2bdcSMaxim Levitsky 1731557d2bdcSMaxim Levitsky /* 1732557d2bdcSMaxim Levitsky * Allocate a temporary key buffer that we will need when 1733557d2bdcSMaxim Levitsky * checking if slot matches the given old password 1734557d2bdcSMaxim Levitsky */ 1735557d2bdcSMaxim Levitsky tmpkey = g_new0(uint8_t, luks->header.master_key_len); 1736557d2bdcSMaxim Levitsky } 1737557d2bdcSMaxim Levitsky 1738557d2bdcSMaxim Levitsky /* Erase an explicitly given keyslot */ 1739557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1740557d2bdcSMaxim Levitsky int keyslot = opts_luks->keyslot; 1741557d2bdcSMaxim Levitsky 1742557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1743557d2bdcSMaxim Levitsky error_setg(errp, 1744557d2bdcSMaxim Levitsky "Invalid keyslot %i specified, must be between 0 and %i", 1745557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1746557d2bdcSMaxim Levitsky return -1; 1747557d2bdcSMaxim Levitsky } 1748557d2bdcSMaxim Levitsky 174916110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1750557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1751557d2bdcSMaxim Levitsky keyslot, 1752557d2bdcSMaxim Levitsky old_password, 1753557d2bdcSMaxim Levitsky tmpkey, 1754557d2bdcSMaxim Levitsky readfunc, 1755557d2bdcSMaxim Levitsky opaque, 1756557d2bdcSMaxim Levitsky errp); 1757557d2bdcSMaxim Levitsky if (rv == -1) { 1758557d2bdcSMaxim Levitsky return -1; 1759557d2bdcSMaxim Levitsky } else if (rv == 0) { 1760557d2bdcSMaxim Levitsky error_setg(errp, 1761557d2bdcSMaxim Levitsky "Given keyslot %i doesn't contain the given " 1762557d2bdcSMaxim Levitsky "old password for erase operation", 1763557d2bdcSMaxim Levitsky keyslot); 1764557d2bdcSMaxim Levitsky return -1; 1765557d2bdcSMaxim Levitsky } 1766557d2bdcSMaxim Levitsky } 1767557d2bdcSMaxim Levitsky 1768557d2bdcSMaxim Levitsky if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { 1769557d2bdcSMaxim Levitsky error_setg(errp, 1770557d2bdcSMaxim Levitsky "Given keyslot %i is already erased (inactive) ", 1771557d2bdcSMaxim Levitsky keyslot); 1772557d2bdcSMaxim Levitsky return -1; 1773557d2bdcSMaxim Levitsky } 1774557d2bdcSMaxim Levitsky 1775557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { 1776557d2bdcSMaxim Levitsky error_setg(errp, 1777557d2bdcSMaxim Levitsky "Attempt to erase the only active keyslot %i " 1778557d2bdcSMaxim Levitsky "which will erase all the data in the image " 1779557d2bdcSMaxim Levitsky "irreversibly - refusing operation", 1780557d2bdcSMaxim Levitsky keyslot); 1781557d2bdcSMaxim Levitsky return -1; 1782557d2bdcSMaxim Levitsky } 1783557d2bdcSMaxim Levitsky 1784557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, keyslot, 1785557d2bdcSMaxim Levitsky writefunc, opaque, errp)) { 1786557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %i", keyslot); 1787557d2bdcSMaxim Levitsky return -1; 1788557d2bdcSMaxim Levitsky } 1789557d2bdcSMaxim Levitsky 1790557d2bdcSMaxim Levitsky /* Erase all keyslots that match the given old password */ 179116110c8bSMarkus Armbruster } else if (opts_luks->old_secret) { 1792557d2bdcSMaxim Levitsky 1793557d2bdcSMaxim Levitsky unsigned long slots_to_erase_bitmap = 0; 1794557d2bdcSMaxim Levitsky size_t i; 1795557d2bdcSMaxim Levitsky int slot_count; 1796557d2bdcSMaxim Levitsky 1797557d2bdcSMaxim Levitsky assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= 1798557d2bdcSMaxim Levitsky sizeof(slots_to_erase_bitmap) * 8); 1799557d2bdcSMaxim Levitsky 1800557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1801557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1802557d2bdcSMaxim Levitsky i, 1803557d2bdcSMaxim Levitsky old_password, 1804557d2bdcSMaxim Levitsky tmpkey, 1805557d2bdcSMaxim Levitsky readfunc, 1806557d2bdcSMaxim Levitsky opaque, 1807557d2bdcSMaxim Levitsky errp); 1808557d2bdcSMaxim Levitsky if (rv == -1) { 1809557d2bdcSMaxim Levitsky return -1; 1810557d2bdcSMaxim Levitsky } else if (rv == 1) { 1811557d2bdcSMaxim Levitsky bitmap_set(&slots_to_erase_bitmap, i, 1); 1812557d2bdcSMaxim Levitsky } 1813557d2bdcSMaxim Levitsky } 1814557d2bdcSMaxim Levitsky 1815557d2bdcSMaxim Levitsky slot_count = bitmap_count_one(&slots_to_erase_bitmap, 1816557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1817557d2bdcSMaxim Levitsky if (slot_count == 0) { 1818557d2bdcSMaxim Levitsky error_setg(errp, 1819557d2bdcSMaxim Levitsky "No keyslots match given (old) password for erase operation"); 1820557d2bdcSMaxim Levitsky return -1; 1821557d2bdcSMaxim Levitsky } 1822557d2bdcSMaxim Levitsky 1823557d2bdcSMaxim Levitsky if (!force && 1824557d2bdcSMaxim Levitsky slot_count == qcrypto_block_luks_count_active_slots(luks)) { 1825557d2bdcSMaxim Levitsky error_setg(errp, 1826557d2bdcSMaxim Levitsky "All the active keyslots match the (old) password that " 1827557d2bdcSMaxim Levitsky "was given and erasing them will erase all the data in " 1828557d2bdcSMaxim Levitsky "the image irreversibly - refusing operation"); 1829557d2bdcSMaxim Levitsky return -1; 1830557d2bdcSMaxim Levitsky } 1831557d2bdcSMaxim Levitsky 1832557d2bdcSMaxim Levitsky /* Now apply the update */ 1833557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1834557d2bdcSMaxim Levitsky if (!test_bit(i, &slots_to_erase_bitmap)) { 1835557d2bdcSMaxim Levitsky continue; 1836557d2bdcSMaxim Levitsky } 1837557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, i, writefunc, 1838557d2bdcSMaxim Levitsky opaque, errp)) { 1839557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %zu", i); 1840557d2bdcSMaxim Levitsky return -1; 1841557d2bdcSMaxim Levitsky } 1842557d2bdcSMaxim Levitsky } 1843557d2bdcSMaxim Levitsky } else { 1844557d2bdcSMaxim Levitsky error_setg(errp, 1845557d2bdcSMaxim Levitsky "To erase keyslot(s), either explicit keyslot index " 1846557d2bdcSMaxim Levitsky "or the password currently contained in them must be given"); 1847557d2bdcSMaxim Levitsky return -1; 1848557d2bdcSMaxim Levitsky } 1849557d2bdcSMaxim Levitsky return 0; 1850557d2bdcSMaxim Levitsky } 1851557d2bdcSMaxim Levitsky 1852557d2bdcSMaxim Levitsky static int 1853557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block, 1854557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1855557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1856557d2bdcSMaxim Levitsky void *opaque, 1857557d2bdcSMaxim Levitsky QCryptoBlockAmendOptions *options, 1858557d2bdcSMaxim Levitsky bool force, 1859557d2bdcSMaxim Levitsky Error **errp) 1860557d2bdcSMaxim Levitsky { 1861557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; 1862557d2bdcSMaxim Levitsky 1863557d2bdcSMaxim Levitsky switch (opts_luks->state) { 1864557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: 1865557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_add_keyslot(block, readfunc, 1866557d2bdcSMaxim Levitsky writefunc, opaque, 1867557d2bdcSMaxim Levitsky opts_luks, force, errp); 1868557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: 1869557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, 1870557d2bdcSMaxim Levitsky writefunc, opaque, 1871557d2bdcSMaxim Levitsky opts_luks, force, errp); 1872557d2bdcSMaxim Levitsky default: 1873557d2bdcSMaxim Levitsky g_assert_not_reached(); 1874557d2bdcSMaxim Levitsky } 1875557d2bdcSMaxim Levitsky } 18763e308f20SDaniel P. Berrange 187740c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 187840c85028SDaniel P. Berrange QCryptoBlockInfo *info, 187940c85028SDaniel P. Berrange Error **errp) 188040c85028SDaniel P. Berrange { 188140c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 188240c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 1883c3033fd3SEric Blake QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots; 188440c85028SDaniel P. Berrange size_t i; 188540c85028SDaniel P. Berrange 188640c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 188740c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 188840c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 188940c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 189040c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 189140c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 189240c85028SDaniel P. Berrange } 189340c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 189440c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 189540c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 189640c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 189740c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 189840c85028SDaniel P. Berrange 189940c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1900c3033fd3SEric Blake slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 190140c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 190240c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1903f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 190440c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 190540c85028SDaniel P. Berrange if (slot->active) { 190640c85028SDaniel P. Berrange slot->has_iters = true; 190740c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 190840c85028SDaniel P. Berrange slot->has_stripes = true; 190940c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 191040c85028SDaniel P. Berrange } 191140c85028SDaniel P. Berrange 1912c3033fd3SEric Blake QAPI_LIST_APPEND(tail, slot); 191340c85028SDaniel P. Berrange } 191440c85028SDaniel P. Berrange 191540c85028SDaniel P. Berrange return 0; 191640c85028SDaniel P. Berrange } 191740c85028SDaniel P. Berrange 191840c85028SDaniel P. Berrange 19193e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 19203e308f20SDaniel P. Berrange { 1921557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1922557d2bdcSMaxim Levitsky if (luks) { 1923557d2bdcSMaxim Levitsky g_free(luks->secret); 1924557d2bdcSMaxim Levitsky g_free(luks); 1925557d2bdcSMaxim Levitsky } 19263e308f20SDaniel P. Berrange } 19273e308f20SDaniel P. Berrange 19283e308f20SDaniel P. Berrange 19293e308f20SDaniel P. Berrange static int 19303e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 19314609742aSDaniel P. Berrange uint64_t offset, 19323e308f20SDaniel P. Berrange uint8_t *buf, 19333e308f20SDaniel P. Berrange size_t len, 19343e308f20SDaniel P. Berrange Error **errp) 19353e308f20SDaniel P. Berrange { 19364609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19374609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19380f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 19393e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19404609742aSDaniel P. Berrange offset, buf, len, errp); 19413e308f20SDaniel P. Berrange } 19423e308f20SDaniel P. Berrange 19433e308f20SDaniel P. Berrange 19443e308f20SDaniel P. Berrange static int 19453e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 19464609742aSDaniel P. Berrange uint64_t offset, 19473e308f20SDaniel P. Berrange uint8_t *buf, 19483e308f20SDaniel P. Berrange size_t len, 19493e308f20SDaniel P. Berrange Error **errp) 19503e308f20SDaniel P. Berrange { 19514609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19524609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19530f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 19543e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19554609742aSDaniel P. Berrange offset, buf, len, errp); 19563e308f20SDaniel P. Berrange } 19573e308f20SDaniel P. Berrange 19583e308f20SDaniel P. Berrange 19593e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 19603e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 19613e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 1962557d2bdcSMaxim Levitsky .amend = qcrypto_block_luks_amend_options, 196340c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 19643e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 19653e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 19663e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 19673e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 19683e308f20SDaniel P. Berrange }; 1969