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 353e308f20SDaniel P. Berrange #include "qemu/coroutine.h" 36557d2bdcSMaxim Levitsky #include "qemu/bitmap.h" 373e308f20SDaniel P. Berrange 383e308f20SDaniel P. Berrange /* 393e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is 403e308f20SDaniel P. Berrange * 413e308f20SDaniel P. Berrange * docs/on-disk-format.pdf 423e308f20SDaniel P. Berrange * 433e308f20SDaniel P. Berrange * in 'cryptsetup' package source code 443e308f20SDaniel P. Berrange * 453e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated 463e308f20SDaniel P. Berrange * Oct 16, 2011. 473e308f20SDaniel P. Berrange */ 483e308f20SDaniel P. Berrange 493e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS; 503e308f20SDaniel P. Berrange 513e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap; 523e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap { 533e308f20SDaniel P. Berrange const char *name; 543e308f20SDaniel P. Berrange int id; 553e308f20SDaniel P. Berrange }; 563e308f20SDaniel P. Berrange 573e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap; 583e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap { 593e308f20SDaniel P. Berrange uint32_t key_bytes; 603e308f20SDaniel P. Berrange int id; 613e308f20SDaniel P. Berrange }; 623e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap; 633e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap { 643e308f20SDaniel P. Berrange const char *name; 653e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes; 663e308f20SDaniel P. Berrange }; 673e308f20SDaniel P. Berrange 683e308f20SDaniel P. Berrange 693e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 703e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = { 713e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 }, 723e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 }, 733e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 }, 743e308f20SDaniel P. Berrange { 0, 0 }, 753e308f20SDaniel P. Berrange }; 763e308f20SDaniel P. Berrange 773e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 783e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = { 793e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 }, 803e308f20SDaniel P. Berrange { 0, 0 }, 813e308f20SDaniel P. Berrange }; 823e308f20SDaniel P. Berrange 833e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 843e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = { 853e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 }, 863e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 }, 873e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 }, 883e308f20SDaniel P. Berrange { 0, 0 }, 893e308f20SDaniel P. Berrange }; 903e308f20SDaniel P. Berrange 913e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 923e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = { 933e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 }, 943e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 }, 953e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 }, 963e308f20SDaniel P. Berrange { 0, 0 }, 973e308f20SDaniel P. Berrange }; 983e308f20SDaniel P. Berrange 993e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap 1003e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = { 1013e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes }, 1023e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, 1033e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, 1043e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, 1053e308f20SDaniel P. Berrange }; 1063e308f20SDaniel P. Berrange 1073e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); 1083e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592); 1093e308f20SDaniel P. Berrange 1103e308f20SDaniel P. Berrange 1113e308f20SDaniel P. Berrange struct QCryptoBlockLUKS { 1123e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header; 11340c85028SDaniel P. Berrange 1149d80e59dSMaxim Levitsky /* Main encryption algorithm used for encryption*/ 11540c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 1169d80e59dSMaxim Levitsky 1179d80e59dSMaxim Levitsky /* Mode of encryption for the selected encryption algorithm */ 11840c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 1199d80e59dSMaxim Levitsky 1209d80e59dSMaxim Levitsky /* Initialization vector generation algorithm */ 12140c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 1229d80e59dSMaxim Levitsky 1239d80e59dSMaxim Levitsky /* Hash algorithm used for IV generation*/ 12440c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 1259d80e59dSMaxim Levitsky 1269d80e59dSMaxim Levitsky /* 1279d80e59dSMaxim Levitsky * Encryption algorithm used for IV generation. 1289d80e59dSMaxim Levitsky * Usually the same as main encryption algorithm 1299d80e59dSMaxim Levitsky */ 1309d80e59dSMaxim Levitsky QCryptoCipherAlgorithm ivgen_cipher_alg; 1319d80e59dSMaxim Levitsky 1329d80e59dSMaxim Levitsky /* Hash algorithm used in pbkdf2 function */ 13340c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 134557d2bdcSMaxim Levitsky 135557d2bdcSMaxim Levitsky /* Name of the secret that was used to open the image */ 136557d2bdcSMaxim Levitsky char *secret; 1373e308f20SDaniel P. Berrange }; 1383e308f20SDaniel P. Berrange 1393e308f20SDaniel P. Berrange 1403e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name, 1413e308f20SDaniel P. Berrange QCryptoCipherMode mode, 1423e308f20SDaniel P. Berrange uint32_t key_bytes, 1433e308f20SDaniel P. Berrange Error **errp) 1443e308f20SDaniel P. Berrange { 1453e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 1463e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 1473e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 1483e308f20SDaniel P. Berrange size_t i, j; 1493e308f20SDaniel P. Berrange 1503e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) { 1513e308f20SDaniel P. Berrange key_bytes /= 2; 1523e308f20SDaniel P. Berrange } 1533e308f20SDaniel P. Berrange 1543e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 1553e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) { 1563e308f20SDaniel P. Berrange continue; 1573e308f20SDaniel P. Berrange } 1583e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 1593e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) { 1603e308f20SDaniel P. Berrange return map[i].sizes[j].id; 1613e308f20SDaniel P. Berrange } 1623e308f20SDaniel P. Berrange } 1633e308f20SDaniel P. Berrange } 1643e308f20SDaniel P. Berrange 1653e308f20SDaniel P. Berrange error_setg(errp, "Algorithm %s with key size %d bytes not supported", 1663e308f20SDaniel P. Berrange name, key_bytes); 1673e308f20SDaniel P. Berrange return 0; 1683e308f20SDaniel P. Berrange } 1693e308f20SDaniel P. Berrange 1703e308f20SDaniel P. Berrange static const char * 1713e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg, 1723e308f20SDaniel P. Berrange Error **errp) 1733e308f20SDaniel P. Berrange { 1743e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 1753e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 1763e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 1773e308f20SDaniel P. Berrange size_t i, j; 1783e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 1793e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 1803e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) { 1813e308f20SDaniel P. Berrange return map[i].name; 1823e308f20SDaniel P. Berrange } 1833e308f20SDaniel P. Berrange } 1843e308f20SDaniel P. Berrange } 1853e308f20SDaniel P. Berrange 1863e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported", 187977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(alg)); 1883e308f20SDaniel P. Berrange return NULL; 1893e308f20SDaniel P. Berrange } 1903e308f20SDaniel P. Berrange 1913e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can 1923e308f20SDaniel P. Berrange * make that function emit a more friendly error message */ 1933e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name, 194f7abe0ecSMarc-André Lureau const QEnumLookup *map, 1953e308f20SDaniel P. Berrange const char *type, 1963e308f20SDaniel P. Berrange Error **errp) 1973e308f20SDaniel P. Berrange { 1989ae33079SMarkus Armbruster int ret = qapi_enum_parse(map, name, -1, NULL); 1993e308f20SDaniel P. Berrange 2009ae33079SMarkus Armbruster if (ret < 0) { 2013e308f20SDaniel P. Berrange error_setg(errp, "%s %s not supported", type, name); 2023e308f20SDaniel P. Berrange return 0; 2033e308f20SDaniel P. Berrange } 2049ae33079SMarkus Armbruster return ret; 2059ae33079SMarkus Armbruster } 2063e308f20SDaniel P. Berrange 2073e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \ 2083e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 209f7abe0ecSMarc-André Lureau &QCryptoCipherMode_lookup, \ 2103e308f20SDaniel P. Berrange "Cipher mode", \ 2113e308f20SDaniel P. Berrange errp) 2123e308f20SDaniel P. Berrange 2133e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \ 2143e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 215f7abe0ecSMarc-André Lureau &QCryptoHashAlgorithm_lookup, \ 2163e308f20SDaniel P. Berrange "Hash algorithm", \ 2173e308f20SDaniel P. Berrange errp) 2183e308f20SDaniel P. Berrange 2193e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \ 2203e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 221f7abe0ecSMarc-André Lureau &QCryptoIVGenAlgorithm_lookup, \ 2223e308f20SDaniel P. Berrange "IV generator", \ 2233e308f20SDaniel P. Berrange errp) 2243e308f20SDaniel P. Berrange 2253e308f20SDaniel P. Berrange 2263e308f20SDaniel P. Berrange static bool 2273e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf, 2283e308f20SDaniel P. Berrange size_t buf_size) 2293e308f20SDaniel P. Berrange { 2303e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf; 2313e308f20SDaniel P. Berrange 2323e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) && 2333e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic, 2343e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 && 2353e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) { 2363e308f20SDaniel P. Berrange return true; 2373e308f20SDaniel P. Berrange } else { 2383e308f20SDaniel P. Berrange return false; 2393e308f20SDaniel P. Berrange } 2403e308f20SDaniel P. Berrange } 2413e308f20SDaniel P. Berrange 2423e308f20SDaniel P. Berrange 2433e308f20SDaniel P. Berrange /** 2443e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV. 2453e308f20SDaniel P. Berrange * 2463e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV 2473e308f20SDaniel P. Berrange * may be different from the cipher length used for the block 2483e308f20SDaniel P. Berrange * encryption, becauses dm-crypt uses the hash digest length 2493e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher 2503e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as 2513e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest 2523e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined 2533e308f20SDaniel P. Berrange */ 2543e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm 2553e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher, 2563e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 2573e308f20SDaniel P. Berrange Error **errp) 2583e308f20SDaniel P. Berrange { 2593e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 2603e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher); 2613e308f20SDaniel P. Berrange if (digestlen == keylen) { 2623e308f20SDaniel P. Berrange return cipher; 2633e308f20SDaniel P. Berrange } 2643e308f20SDaniel P. Berrange 2653e308f20SDaniel P. Berrange switch (cipher) { 2663e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128: 2673e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192: 2683e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256: 2693e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 2703e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) { 2713e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128; 2723e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2733e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) { 2743e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192; 2753e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2763e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) { 2773e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256; 2783e308f20SDaniel P. Berrange } else { 2793e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available", 2803e308f20SDaniel P. Berrange digestlen); 2813e308f20SDaniel P. Berrange return 0; 2823e308f20SDaniel P. Berrange } 2833e308f20SDaniel P. Berrange break; 2843e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128: 2853e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192: 2863e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256: 2873e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 2883e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) { 2893e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128; 2903e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2913e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) { 2923e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192; 2933e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2943e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) { 2953e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256; 2963e308f20SDaniel P. Berrange } else { 2973e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available", 2983e308f20SDaniel P. Berrange digestlen); 2993e308f20SDaniel P. Berrange return 0; 3003e308f20SDaniel P. Berrange } 3013e308f20SDaniel P. Berrange break; 3023e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128: 3033e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192: 3043e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256: 3053e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3063e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) { 3073e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128; 3083e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3093e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) { 3103e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192; 3113e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3123e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) { 3133e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256; 3143e308f20SDaniel P. Berrange } else { 3153e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available", 3163e308f20SDaniel P. Berrange digestlen); 3173e308f20SDaniel P. Berrange return 0; 3183e308f20SDaniel P. Berrange } 3193e308f20SDaniel P. Berrange break; 3203e308f20SDaniel P. Berrange default: 3213e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv", 322977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(cipher)); 3233e308f20SDaniel P. Berrange return 0; 3243e308f20SDaniel P. Berrange } 3253e308f20SDaniel P. Berrange } 3263e308f20SDaniel P. Berrange 3273e308f20SDaniel P. Berrange /* 328bd56a55aSMaxim Levitsky * Returns number of sectors needed to store the key material 329bd56a55aSMaxim Levitsky * given number of anti forensic stripes 330bd56a55aSMaxim Levitsky */ 331bd56a55aSMaxim Levitsky static int 332bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks, 333bd56a55aSMaxim Levitsky unsigned int header_sectors, 334bd56a55aSMaxim Levitsky unsigned int stripes) 335bd56a55aSMaxim Levitsky { 336bd56a55aSMaxim Levitsky /* 337bd56a55aSMaxim Levitsky * This calculation doesn't match that shown in the spec, 338bd56a55aSMaxim Levitsky * but instead follows the cryptsetup implementation. 339bd56a55aSMaxim Levitsky */ 340bd56a55aSMaxim Levitsky 341bd56a55aSMaxim Levitsky size_t splitkeylen = luks->header.master_key_len * stripes; 342bd56a55aSMaxim Levitsky 343bd56a55aSMaxim Levitsky /* First align the key material size to block size*/ 344bd56a55aSMaxim Levitsky size_t splitkeylen_sectors = 345bd56a55aSMaxim Levitsky DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE); 346bd56a55aSMaxim Levitsky 347bd56a55aSMaxim Levitsky /* Then also align the key material size to the size of the header */ 348bd56a55aSMaxim Levitsky return ROUND_UP(splitkeylen_sectors, header_sectors); 349bd56a55aSMaxim Levitsky } 350bd56a55aSMaxim Levitsky 351bd56a55aSMaxim Levitsky /* 352dde2c5afSMaxim Levitsky * Stores the main LUKS header, taking care of endianess 353dde2c5afSMaxim Levitsky */ 354dde2c5afSMaxim Levitsky static int 355dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block, 356dde2c5afSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 357dde2c5afSMaxim Levitsky void *opaque, 358dde2c5afSMaxim Levitsky Error **errp) 359dde2c5afSMaxim Levitsky { 360dde2c5afSMaxim Levitsky const QCryptoBlockLUKS *luks = block->opaque; 361dde2c5afSMaxim Levitsky Error *local_err = NULL; 362dde2c5afSMaxim Levitsky size_t i; 363dde2c5afSMaxim Levitsky g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL; 364dde2c5afSMaxim Levitsky 365dde2c5afSMaxim Levitsky /* Create a copy of the header */ 366dde2c5afSMaxim Levitsky hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1); 367dde2c5afSMaxim Levitsky memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader)); 368dde2c5afSMaxim Levitsky 369dde2c5afSMaxim Levitsky /* 370dde2c5afSMaxim Levitsky * Everything on disk uses Big Endian (tm), so flip header fields 371dde2c5afSMaxim Levitsky * before writing them 372dde2c5afSMaxim Levitsky */ 373dde2c5afSMaxim Levitsky cpu_to_be16s(&hdr_copy->version); 374dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->payload_offset_sector); 375dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->master_key_len); 376dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->master_key_iterations); 377dde2c5afSMaxim Levitsky 378dde2c5afSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 379dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].active); 380dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].iterations); 381dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].key_offset_sector); 382dde2c5afSMaxim Levitsky cpu_to_be32s(&hdr_copy->key_slots[i].stripes); 383dde2c5afSMaxim Levitsky } 384dde2c5afSMaxim Levitsky 385dde2c5afSMaxim Levitsky /* Write out the partition header and key slot headers */ 386dde2c5afSMaxim Levitsky writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy), 387dde2c5afSMaxim Levitsky opaque, &local_err); 388dde2c5afSMaxim Levitsky 389dde2c5afSMaxim Levitsky if (local_err) { 390dde2c5afSMaxim Levitsky error_propagate(errp, local_err); 391dde2c5afSMaxim Levitsky return -1; 392dde2c5afSMaxim Levitsky } 393dde2c5afSMaxim Levitsky return 0; 394dde2c5afSMaxim Levitsky } 395dde2c5afSMaxim Levitsky 396dde2c5afSMaxim Levitsky /* 397dde2c5afSMaxim Levitsky * Loads the main LUKS header,and byteswaps it to native endianess 398dde2c5afSMaxim Levitsky * And run basic sanity checks on it 399dde2c5afSMaxim Levitsky */ 400dde2c5afSMaxim Levitsky static int 401dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block, 402dde2c5afSMaxim Levitsky QCryptoBlockReadFunc readfunc, 403dde2c5afSMaxim Levitsky void *opaque, 404dde2c5afSMaxim Levitsky Error **errp) 405dde2c5afSMaxim Levitsky { 406757dda54SAlberto Faria int rv; 407dde2c5afSMaxim Levitsky size_t i; 408dde2c5afSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 409dde2c5afSMaxim Levitsky 410dde2c5afSMaxim Levitsky /* 411dde2c5afSMaxim Levitsky * Read the entire LUKS header, minus the key material from 412dde2c5afSMaxim Levitsky * the underlying device 413dde2c5afSMaxim Levitsky */ 414dde2c5afSMaxim Levitsky rv = readfunc(block, 0, 415dde2c5afSMaxim Levitsky (uint8_t *)&luks->header, 416dde2c5afSMaxim Levitsky sizeof(luks->header), 417dde2c5afSMaxim Levitsky opaque, 418dde2c5afSMaxim Levitsky errp); 419dde2c5afSMaxim Levitsky if (rv < 0) { 420dde2c5afSMaxim Levitsky return rv; 421dde2c5afSMaxim Levitsky } 422dde2c5afSMaxim Levitsky 423dde2c5afSMaxim Levitsky /* 424dde2c5afSMaxim Levitsky * The header is always stored in big-endian format, so 425dde2c5afSMaxim Levitsky * convert everything to native 426dde2c5afSMaxim Levitsky */ 427dde2c5afSMaxim Levitsky be16_to_cpus(&luks->header.version); 428dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.payload_offset_sector); 429dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.master_key_len); 430dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.master_key_iterations); 431dde2c5afSMaxim Levitsky 432dde2c5afSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 433dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].active); 434dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].iterations); 435dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].key_offset_sector); 436dde2c5afSMaxim Levitsky be32_to_cpus(&luks->header.key_slots[i].stripes); 437dde2c5afSMaxim Levitsky } 438dde2c5afSMaxim Levitsky 439dde2c5afSMaxim Levitsky return 0; 440dde2c5afSMaxim Levitsky } 441dde2c5afSMaxim Levitsky 442dde2c5afSMaxim Levitsky /* 4439fa9c1c2SMaxim Levitsky * Does basic sanity checks on the LUKS header 4449fa9c1c2SMaxim Levitsky */ 4459fa9c1c2SMaxim Levitsky static int 4469fa9c1c2SMaxim Levitsky qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp) 4479fa9c1c2SMaxim Levitsky { 448befdba9eSMaxim Levitsky size_t i, j; 449befdba9eSMaxim Levitsky 450befdba9eSMaxim Levitsky unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 451befdba9eSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 452befdba9eSMaxim Levitsky 4539fa9c1c2SMaxim Levitsky if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 4549fa9c1c2SMaxim Levitsky QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 4559fa9c1c2SMaxim Levitsky error_setg(errp, "Volume is not in LUKS format"); 4569fa9c1c2SMaxim Levitsky return -1; 4579fa9c1c2SMaxim Levitsky } 4589fa9c1c2SMaxim Levitsky 4599fa9c1c2SMaxim Levitsky if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 4609fa9c1c2SMaxim Levitsky error_setg(errp, "LUKS version %" PRIu32 " is not supported", 4619fa9c1c2SMaxim Levitsky luks->header.version); 4629fa9c1c2SMaxim Levitsky return -1; 4639fa9c1c2SMaxim Levitsky } 464befdba9eSMaxim Levitsky 465c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_name, '\0', 466c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_name))) { 467c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher name is not NUL terminated"); 468c1d8634cSDaniel P. Berrangé return -1; 469c1d8634cSDaniel P. Berrangé } 470c1d8634cSDaniel P. Berrangé 471c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_mode, '\0', 472c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_mode))) { 473c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher mode is not NUL terminated"); 474c1d8634cSDaniel P. Berrangé return -1; 475c1d8634cSDaniel P. Berrangé } 476c1d8634cSDaniel P. Berrangé 477c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.hash_spec, '\0', 478c1d8634cSDaniel P. Berrangé sizeof(luks->header.hash_spec))) { 479c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header hash spec is not NUL terminated"); 480c1d8634cSDaniel P. Berrangé return -1; 481c1d8634cSDaniel P. Berrangé } 482c1d8634cSDaniel P. Berrangé 483d233fbc3SDaniel P. Berrangé if (luks->header.payload_offset_sector < 484d233fbc3SDaniel P. Berrangé DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 485d233fbc3SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 486d233fbc3SDaniel P. Berrangé error_setg(errp, "LUKS payload is overlapping with the header"); 487d233fbc3SDaniel P. Berrangé return -1; 488d233fbc3SDaniel P. Berrangé } 489d233fbc3SDaniel P. Berrangé 490b57151acSDaniel P. Berrangé if (luks->header.master_key_iterations == 0) { 491b57151acSDaniel P. Berrangé error_setg(errp, "LUKS key iteration count is zero"); 492b57151acSDaniel P. Berrangé return -1; 493b57151acSDaniel P. Berrangé } 494b57151acSDaniel P. Berrangé 495befdba9eSMaxim Levitsky /* Check all keyslots for corruption */ 496befdba9eSMaxim Levitsky for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) { 497befdba9eSMaxim Levitsky 498befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i]; 499befdba9eSMaxim Levitsky unsigned int start1 = slot1->key_offset_sector; 500befdba9eSMaxim Levitsky unsigned int len1 = 501befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 502befdba9eSMaxim Levitsky header_sectors, 503befdba9eSMaxim Levitsky slot1->stripes); 504befdba9eSMaxim Levitsky 505f1195961SDaniel P. Berrangé if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) { 506f1195961SDaniel P. Berrangé error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)", 507f1195961SDaniel P. Berrangé i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES); 508befdba9eSMaxim Levitsky return -1; 509befdba9eSMaxim Levitsky } 510befdba9eSMaxim Levitsky 511befdba9eSMaxim Levitsky if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED && 512befdba9eSMaxim Levitsky slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 513befdba9eSMaxim Levitsky error_setg(errp, 514befdba9eSMaxim Levitsky "Keyslot %zu state (active/disable) is corrupted", i); 515befdba9eSMaxim Levitsky return -1; 516befdba9eSMaxim Levitsky } 517befdba9eSMaxim Levitsky 518b57151acSDaniel P. Berrangé if (slot1->active == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED && 519b57151acSDaniel P. Berrangé slot1->iterations == 0) { 520b57151acSDaniel P. Berrangé error_setg(errp, "Keyslot %zu iteration count is zero", i); 521b57151acSDaniel P. Berrangé return -1; 522b57151acSDaniel P. Berrangé } 523b57151acSDaniel P. Berrangé 524c5f69628SDaniel P. Berrangé if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 52593569c37SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 52693569c37SDaniel P. Berrangé error_setg(errp, 52793569c37SDaniel P. Berrangé "Keyslot %zu is overlapping with the LUKS header", 52893569c37SDaniel P. Berrangé i); 52993569c37SDaniel P. Berrangé return -1; 53093569c37SDaniel P. Berrangé } 53193569c37SDaniel P. Berrangé 532befdba9eSMaxim Levitsky if (start1 + len1 > luks->header.payload_offset_sector) { 533befdba9eSMaxim Levitsky error_setg(errp, 534befdba9eSMaxim Levitsky "Keyslot %zu is overlapping with the encrypted payload", 535befdba9eSMaxim Levitsky i); 536befdba9eSMaxim Levitsky return -1; 537befdba9eSMaxim Levitsky } 538befdba9eSMaxim Levitsky 539befdba9eSMaxim Levitsky for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) { 540befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j]; 541befdba9eSMaxim Levitsky unsigned int start2 = slot2->key_offset_sector; 542befdba9eSMaxim Levitsky unsigned int len2 = 543befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 544befdba9eSMaxim Levitsky header_sectors, 545befdba9eSMaxim Levitsky slot2->stripes); 546befdba9eSMaxim Levitsky 547befdba9eSMaxim Levitsky if (start1 + len1 > start2 && start2 + len2 > start1) { 548befdba9eSMaxim Levitsky error_setg(errp, 549befdba9eSMaxim Levitsky "Keyslots %zu and %zu are overlapping in the header", 550befdba9eSMaxim Levitsky i, j); 551befdba9eSMaxim Levitsky return -1; 552befdba9eSMaxim Levitsky } 553befdba9eSMaxim Levitsky } 554befdba9eSMaxim Levitsky 555befdba9eSMaxim Levitsky } 5569fa9c1c2SMaxim Levitsky return 0; 5579fa9c1c2SMaxim Levitsky } 5589fa9c1c2SMaxim Levitsky 5599fa9c1c2SMaxim Levitsky /* 5609fa9c1c2SMaxim Levitsky * Parses the crypto parameters that are stored in the LUKS header 5619fa9c1c2SMaxim Levitsky */ 5629fa9c1c2SMaxim Levitsky 5639fa9c1c2SMaxim Levitsky static int 5649fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp) 5659fa9c1c2SMaxim Levitsky { 5669fa9c1c2SMaxim Levitsky g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode); 5679fa9c1c2SMaxim Levitsky char *ivgen_name, *ivhash_name; 5689fa9c1c2SMaxim Levitsky Error *local_err = NULL; 5699fa9c1c2SMaxim Levitsky 5709fa9c1c2SMaxim Levitsky /* 5719fa9c1c2SMaxim Levitsky * The cipher_mode header contains a string that we have 5729fa9c1c2SMaxim Levitsky * to further parse, of the format 5739fa9c1c2SMaxim Levitsky * 5749fa9c1c2SMaxim Levitsky * <cipher-mode>-<iv-generator>[:<iv-hash>] 5759fa9c1c2SMaxim Levitsky * 5769fa9c1c2SMaxim Levitsky * eg cbc-essiv:sha256, cbc-plain64 5779fa9c1c2SMaxim Levitsky */ 5789fa9c1c2SMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 5799fa9c1c2SMaxim Levitsky if (!ivgen_name) { 5809fa9c1c2SMaxim Levitsky error_setg(errp, "Unexpected cipher mode string format %s", 5819fa9c1c2SMaxim Levitsky luks->header.cipher_mode); 5829fa9c1c2SMaxim Levitsky return -1; 5839fa9c1c2SMaxim Levitsky } 5849fa9c1c2SMaxim Levitsky *ivgen_name = '\0'; 5859fa9c1c2SMaxim Levitsky ivgen_name++; 5869fa9c1c2SMaxim Levitsky 5879fa9c1c2SMaxim Levitsky ivhash_name = strchr(ivgen_name, ':'); 5889fa9c1c2SMaxim Levitsky if (!ivhash_name) { 5899fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = 0; 5909fa9c1c2SMaxim Levitsky } else { 5919fa9c1c2SMaxim Levitsky *ivhash_name = '\0'; 5929fa9c1c2SMaxim Levitsky ivhash_name++; 5939fa9c1c2SMaxim Levitsky 5949fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 5959fa9c1c2SMaxim Levitsky &local_err); 5969fa9c1c2SMaxim Levitsky if (local_err) { 5979fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 5989fa9c1c2SMaxim Levitsky return -1; 5999fa9c1c2SMaxim Levitsky } 6009fa9c1c2SMaxim Levitsky } 6019fa9c1c2SMaxim Levitsky 6029fa9c1c2SMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 6039fa9c1c2SMaxim Levitsky &local_err); 6049fa9c1c2SMaxim Levitsky if (local_err) { 6059fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6069fa9c1c2SMaxim Levitsky return -1; 6079fa9c1c2SMaxim Levitsky } 6089fa9c1c2SMaxim Levitsky 6099fa9c1c2SMaxim Levitsky luks->cipher_alg = 6109fa9c1c2SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 6119fa9c1c2SMaxim Levitsky luks->cipher_mode, 6129fa9c1c2SMaxim Levitsky luks->header.master_key_len, 6139fa9c1c2SMaxim Levitsky &local_err); 6149fa9c1c2SMaxim Levitsky if (local_err) { 6159fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6169fa9c1c2SMaxim Levitsky return -1; 6179fa9c1c2SMaxim Levitsky } 6189fa9c1c2SMaxim Levitsky 6199fa9c1c2SMaxim Levitsky luks->hash_alg = 6209fa9c1c2SMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 6219fa9c1c2SMaxim Levitsky &local_err); 6229fa9c1c2SMaxim Levitsky if (local_err) { 6239fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6249fa9c1c2SMaxim Levitsky return -1; 6259fa9c1c2SMaxim Levitsky } 6269fa9c1c2SMaxim Levitsky 6279fa9c1c2SMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 6289fa9c1c2SMaxim Levitsky &local_err); 6299fa9c1c2SMaxim Levitsky if (local_err) { 6309fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6319fa9c1c2SMaxim Levitsky return -1; 6329fa9c1c2SMaxim Levitsky } 6339fa9c1c2SMaxim Levitsky 6349fa9c1c2SMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 6359fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6369fa9c1c2SMaxim Levitsky error_setg(errp, "Missing IV generator hash specification"); 6379fa9c1c2SMaxim Levitsky return -1; 6389fa9c1c2SMaxim Levitsky } 6399fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = 6409fa9c1c2SMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 6419fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg, 6429fa9c1c2SMaxim Levitsky &local_err); 6439fa9c1c2SMaxim Levitsky if (local_err) { 6449fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6459fa9c1c2SMaxim Levitsky return -1; 6469fa9c1c2SMaxim Levitsky } 6479fa9c1c2SMaxim Levitsky } else { 6489fa9c1c2SMaxim Levitsky 6499fa9c1c2SMaxim Levitsky /* 6509fa9c1c2SMaxim Levitsky * Note we parsed the ivhash_name earlier in the cipher_mode 6519fa9c1c2SMaxim Levitsky * spec string even with plain/plain64 ivgens, but we 6529fa9c1c2SMaxim Levitsky * will ignore it, since it is irrelevant for these ivgens. 6539fa9c1c2SMaxim Levitsky * This is for compat with dm-crypt which will silently 6549fa9c1c2SMaxim Levitsky * ignore hash names with these ivgens rather than report 6559fa9c1c2SMaxim Levitsky * an error about the invalid usage 6569fa9c1c2SMaxim Levitsky */ 6579fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 6589fa9c1c2SMaxim Levitsky } 6599fa9c1c2SMaxim Levitsky return 0; 6609fa9c1c2SMaxim Levitsky } 6619fa9c1c2SMaxim Levitsky 6629fa9c1c2SMaxim Levitsky /* 6633994a7c9SMaxim Levitsky * Given a key slot, user password, and the master key, 6643994a7c9SMaxim Levitsky * will store the encrypted master key there, and update the 6653994a7c9SMaxim Levitsky * in-memory header. User must then write the in-memory header 6663994a7c9SMaxim Levitsky * 6673994a7c9SMaxim Levitsky * Returns: 6683994a7c9SMaxim Levitsky * 0 if the keyslot was written successfully 6693994a7c9SMaxim Levitsky * with the provided password 6703994a7c9SMaxim Levitsky * -1 if a fatal error occurred while storing the key 6713994a7c9SMaxim Levitsky */ 6723994a7c9SMaxim Levitsky static int 6733994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block, 6743994a7c9SMaxim Levitsky unsigned int slot_idx, 6753994a7c9SMaxim Levitsky const char *password, 6763994a7c9SMaxim Levitsky uint8_t *masterkey, 6773994a7c9SMaxim Levitsky uint64_t iter_time, 6783994a7c9SMaxim Levitsky QCryptoBlockWriteFunc writefunc, 6793994a7c9SMaxim Levitsky void *opaque, 6803994a7c9SMaxim Levitsky Error **errp) 6813994a7c9SMaxim Levitsky { 6823994a7c9SMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 683557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 6843994a7c9SMaxim Levitsky g_autofree uint8_t *splitkey = NULL; 6853994a7c9SMaxim Levitsky size_t splitkeylen; 6863994a7c9SMaxim Levitsky g_autofree uint8_t *slotkey = NULL; 6873994a7c9SMaxim Levitsky g_autoptr(QCryptoCipher) cipher = NULL; 6883994a7c9SMaxim Levitsky g_autoptr(QCryptoIVGen) ivgen = NULL; 6893994a7c9SMaxim Levitsky Error *local_err = NULL; 6903994a7c9SMaxim Levitsky uint64_t iters; 6913994a7c9SMaxim Levitsky int ret = -1; 6923994a7c9SMaxim Levitsky 693557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 694557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 6953994a7c9SMaxim Levitsky if (qcrypto_random_bytes(slot->salt, 6963994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 6973994a7c9SMaxim Levitsky errp) < 0) { 6983994a7c9SMaxim Levitsky goto cleanup; 6993994a7c9SMaxim Levitsky } 7003994a7c9SMaxim Levitsky 7013994a7c9SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 7023994a7c9SMaxim Levitsky 7033994a7c9SMaxim Levitsky /* 7043994a7c9SMaxim Levitsky * Determine how many iterations are required to 7053994a7c9SMaxim Levitsky * hash the user password while consuming 1 second of compute 7063994a7c9SMaxim Levitsky * time 7073994a7c9SMaxim Levitsky */ 7083994a7c9SMaxim Levitsky iters = qcrypto_pbkdf2_count_iters(luks->hash_alg, 7093994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7103994a7c9SMaxim Levitsky slot->salt, 7113994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7123994a7c9SMaxim Levitsky luks->header.master_key_len, 7133994a7c9SMaxim Levitsky &local_err); 7143994a7c9SMaxim Levitsky if (local_err) { 7153994a7c9SMaxim Levitsky error_propagate(errp, local_err); 7163994a7c9SMaxim Levitsky goto cleanup; 7173994a7c9SMaxim Levitsky } 7183994a7c9SMaxim Levitsky 7193994a7c9SMaxim Levitsky if (iters > (ULLONG_MAX / iter_time)) { 7203994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7213994a7c9SMaxim Levitsky "PBKDF iterations %llu too large to scale", 7223994a7c9SMaxim Levitsky (unsigned long long)iters); 7233994a7c9SMaxim Levitsky goto cleanup; 7243994a7c9SMaxim Levitsky } 7253994a7c9SMaxim Levitsky 7263994a7c9SMaxim Levitsky /* iter_time was in millis, but count_iters reported for secs */ 7273994a7c9SMaxim Levitsky iters = iters * iter_time / 1000; 7283994a7c9SMaxim Levitsky 7293994a7c9SMaxim Levitsky if (iters > UINT32_MAX) { 7303994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7313994a7c9SMaxim Levitsky "PBKDF iterations %llu larger than %u", 7323994a7c9SMaxim Levitsky (unsigned long long)iters, UINT32_MAX); 7333994a7c9SMaxim Levitsky goto cleanup; 7343994a7c9SMaxim Levitsky } 7353994a7c9SMaxim Levitsky 7363994a7c9SMaxim Levitsky slot->iterations = 7373994a7c9SMaxim Levitsky MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 7383994a7c9SMaxim Levitsky 7393994a7c9SMaxim Levitsky 7403994a7c9SMaxim Levitsky /* 7413994a7c9SMaxim Levitsky * Generate a key that we'll use to encrypt the master 7423994a7c9SMaxim Levitsky * key, from the user's password 7433994a7c9SMaxim Levitsky */ 7443994a7c9SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 7453994a7c9SMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 7463994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7473994a7c9SMaxim Levitsky slot->salt, 7483994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7493994a7c9SMaxim Levitsky slot->iterations, 7503994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7513994a7c9SMaxim Levitsky errp) < 0) { 7523994a7c9SMaxim Levitsky goto cleanup; 7533994a7c9SMaxim Levitsky } 7543994a7c9SMaxim Levitsky 7553994a7c9SMaxim Levitsky 7563994a7c9SMaxim Levitsky /* 7573994a7c9SMaxim Levitsky * Setup the encryption objects needed to encrypt the 7583994a7c9SMaxim Levitsky * master key material 7593994a7c9SMaxim Levitsky */ 7603994a7c9SMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 7613994a7c9SMaxim Levitsky luks->cipher_mode, 7623994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7633994a7c9SMaxim Levitsky errp); 7643994a7c9SMaxim Levitsky if (!cipher) { 7653994a7c9SMaxim Levitsky goto cleanup; 7663994a7c9SMaxim Levitsky } 7673994a7c9SMaxim Levitsky 7683994a7c9SMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 7693994a7c9SMaxim Levitsky luks->ivgen_cipher_alg, 7703994a7c9SMaxim Levitsky luks->ivgen_hash_alg, 7713994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7723994a7c9SMaxim Levitsky errp); 7733994a7c9SMaxim Levitsky if (!ivgen) { 7743994a7c9SMaxim Levitsky goto cleanup; 7753994a7c9SMaxim Levitsky } 7763994a7c9SMaxim Levitsky 7773994a7c9SMaxim Levitsky /* 7783994a7c9SMaxim Levitsky * Before storing the master key, we need to vastly 7793994a7c9SMaxim Levitsky * increase its size, as protection against forensic 7803994a7c9SMaxim Levitsky * disk data recovery 7813994a7c9SMaxim Levitsky */ 7823994a7c9SMaxim Levitsky splitkey = g_new0(uint8_t, splitkeylen); 7833994a7c9SMaxim Levitsky 7843994a7c9SMaxim Levitsky if (qcrypto_afsplit_encode(luks->hash_alg, 7853994a7c9SMaxim Levitsky luks->header.master_key_len, 7863994a7c9SMaxim Levitsky slot->stripes, 7873994a7c9SMaxim Levitsky masterkey, 7883994a7c9SMaxim Levitsky splitkey, 7893994a7c9SMaxim Levitsky errp) < 0) { 7903994a7c9SMaxim Levitsky goto cleanup; 7913994a7c9SMaxim Levitsky } 7923994a7c9SMaxim Levitsky 7933994a7c9SMaxim Levitsky /* 7943994a7c9SMaxim Levitsky * Now we encrypt the split master key with the key generated 7953994a7c9SMaxim Levitsky * from the user's password, before storing it 7963994a7c9SMaxim Levitsky */ 7973994a7c9SMaxim Levitsky if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 7983994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 7993994a7c9SMaxim Levitsky 0, 8003994a7c9SMaxim Levitsky splitkey, 8013994a7c9SMaxim Levitsky splitkeylen, 8023994a7c9SMaxim Levitsky errp) < 0) { 8033994a7c9SMaxim Levitsky goto cleanup; 8043994a7c9SMaxim Levitsky } 8053994a7c9SMaxim Levitsky 8063994a7c9SMaxim Levitsky /* Write out the slot's master key material. */ 8073994a7c9SMaxim Levitsky if (writefunc(block, 8083994a7c9SMaxim Levitsky slot->key_offset_sector * 8093994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8103994a7c9SMaxim Levitsky splitkey, splitkeylen, 8113994a7c9SMaxim Levitsky opaque, 812757dda54SAlberto Faria errp) < 0) { 8133994a7c9SMaxim Levitsky goto cleanup; 8143994a7c9SMaxim Levitsky } 8153994a7c9SMaxim Levitsky 8163994a7c9SMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 8173994a7c9SMaxim Levitsky 8183994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) { 8193994a7c9SMaxim Levitsky goto cleanup; 8203994a7c9SMaxim Levitsky } 8213994a7c9SMaxim Levitsky 8223994a7c9SMaxim Levitsky ret = 0; 8233994a7c9SMaxim Levitsky 8243994a7c9SMaxim Levitsky cleanup: 8253994a7c9SMaxim Levitsky if (slotkey) { 8263994a7c9SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 8273994a7c9SMaxim Levitsky } 8283994a7c9SMaxim Levitsky if (splitkey) { 8293994a7c9SMaxim Levitsky memset(splitkey, 0, splitkeylen); 8303994a7c9SMaxim Levitsky } 8313994a7c9SMaxim Levitsky return ret; 8323994a7c9SMaxim Levitsky } 8333994a7c9SMaxim Levitsky 8343994a7c9SMaxim Levitsky /* 8353e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 8363e308f20SDaniel P. Berrange * the master encryption key from the key slot. 8373e308f20SDaniel P. Berrange * 8383e308f20SDaniel P. Berrange * Returns: 8393e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 8403e308f20SDaniel P. Berrange * with the provided password 8413e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 8423e308f20SDaniel P. Berrange * with the provided password 8433e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 8443e308f20SDaniel P. Berrange */ 8453e308f20SDaniel P. Berrange static int 8463e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 8477e60a6f5SMaxim Levitsky size_t slot_idx, 8483e308f20SDaniel P. Berrange const char *password, 8493e308f20SDaniel P. Berrange uint8_t *masterkey, 8503e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 8513e308f20SDaniel P. Berrange void *opaque, 8523e308f20SDaniel P. Berrange Error **errp) 8533e308f20SDaniel P. Berrange { 8543e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 855557d2bdcSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot; 85657b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 8573e308f20SDaniel P. Berrange size_t splitkeylen; 85857b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 859757dda54SAlberto Faria int rv; 86057b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 8613e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 86257b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 8633e308f20SDaniel P. Berrange size_t niv; 8643e308f20SDaniel P. Berrange 865557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 866557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 8673e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 8683e308f20SDaniel P. Berrange return 0; 8693e308f20SDaniel P. Berrange } 8703e308f20SDaniel P. Berrange 8711ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 8723e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 8731ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 8743e308f20SDaniel P. Berrange 8753e308f20SDaniel P. Berrange /* 8763e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 8773e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 8783e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 8793e308f20SDaniel P. Berrange * the key is correct and validate the results of 8803e308f20SDaniel P. Berrange * decryption later. 8813e308f20SDaniel P. Berrange */ 8829d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 8833e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 8843e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 8853e308f20SDaniel P. Berrange slot->iterations, 8861ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 8873e308f20SDaniel P. Berrange errp) < 0) { 88857b9f113SDaniel P. Berrangé return -1; 8893e308f20SDaniel P. Berrange } 8903e308f20SDaniel P. Berrange 8913e308f20SDaniel P. Berrange /* 8923e308f20SDaniel P. Berrange * We need to read the master key material from the 8933e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 8943e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 8953e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 8963e308f20SDaniel P. Berrange * then encrypted. 8973e308f20SDaniel P. Berrange */ 8983e308f20SDaniel P. Berrange rv = readfunc(block, 899f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9003e308f20SDaniel P. Berrange splitkey, splitkeylen, 901e4a3507eSDaniel P. Berrange opaque, 90237509233SFam Zheng errp); 9033e308f20SDaniel P. Berrange if (rv < 0) { 90457b9f113SDaniel P. Berrangé return -1; 9053e308f20SDaniel P. Berrange } 9063e308f20SDaniel P. Berrange 9073e308f20SDaniel P. Berrange 9083e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 9093e308f20SDaniel P. Berrange * the split master key material */ 9109d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 9119d80e59dSMaxim Levitsky luks->cipher_mode, 9129d80e59dSMaxim Levitsky possiblekey, 9139d80e59dSMaxim Levitsky luks->header.master_key_len, 9143e308f20SDaniel P. Berrange errp); 9153e308f20SDaniel P. Berrange if (!cipher) { 91657b9f113SDaniel P. Berrangé return -1; 9173e308f20SDaniel P. Berrange } 9183e308f20SDaniel P. Berrange 9199d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 9209d80e59dSMaxim Levitsky luks->cipher_mode); 9219d80e59dSMaxim Levitsky 9229d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 9239d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 9249d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 9259d80e59dSMaxim Levitsky possiblekey, 9269d80e59dSMaxim Levitsky luks->header.master_key_len, 9273e308f20SDaniel P. Berrange errp); 9283e308f20SDaniel P. Berrange if (!ivgen) { 92957b9f113SDaniel P. Berrangé return -1; 9303e308f20SDaniel P. Berrange } 9313e308f20SDaniel P. Berrange 9323e308f20SDaniel P. Berrange 9333e308f20SDaniel P. Berrange /* 9343e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 9353e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 9363e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 9373e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 9383e308f20SDaniel P. Berrange * key crosses a sector boundary. 9393e308f20SDaniel P. Berrange */ 9400270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 9413e308f20SDaniel P. Berrange niv, 9423e308f20SDaniel P. Berrange ivgen, 9433e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9443e308f20SDaniel P. Berrange 0, 9453e308f20SDaniel P. Berrange splitkey, 9463e308f20SDaniel P. Berrange splitkeylen, 9473e308f20SDaniel P. Berrange errp) < 0) { 94857b9f113SDaniel P. Berrangé return -1; 9493e308f20SDaniel P. Berrange } 9503e308f20SDaniel P. Berrange 9513e308f20SDaniel P. Berrange /* 9523e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 9533e308f20SDaniel P. Berrange * it back together to get the actual master key. 9543e308f20SDaniel P. Berrange */ 9559d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 9561ddd52e4SMaxim Levitsky luks->header.master_key_len, 9573e308f20SDaniel P. Berrange slot->stripes, 9583e308f20SDaniel P. Berrange splitkey, 9593e308f20SDaniel P. Berrange masterkey, 9603e308f20SDaniel P. Berrange errp) < 0) { 96157b9f113SDaniel P. Berrangé return -1; 9623e308f20SDaniel P. Berrange } 9633e308f20SDaniel P. Berrange 9643e308f20SDaniel P. Berrange 9653e308f20SDaniel P. Berrange /* 9663e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 9673e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 9683e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 9693e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 9703e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 9713e308f20SDaniel P. Berrange * header 9723e308f20SDaniel P. Berrange */ 9739d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 9741ddd52e4SMaxim Levitsky masterkey, 9751ddd52e4SMaxim Levitsky luks->header.master_key_len, 9763e308f20SDaniel P. Berrange luks->header.master_key_salt, 9773e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 9783e308f20SDaniel P. Berrange luks->header.master_key_iterations, 9791ddd52e4SMaxim Levitsky keydigest, 9801ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 9813e308f20SDaniel P. Berrange errp) < 0) { 98257b9f113SDaniel P. Berrangé return -1; 9833e308f20SDaniel P. Berrange } 9843e308f20SDaniel P. Berrange 9853e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 9863e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 9873e308f20SDaniel P. Berrange /* Success, we got the right master key */ 98857b9f113SDaniel P. Berrangé return 1; 9893e308f20SDaniel P. Berrange } 9903e308f20SDaniel P. Berrange 9913e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 9923e308f20SDaniel P. Berrange * tell caller to try another slot */ 99357b9f113SDaniel P. Berrangé return 0; 9943e308f20SDaniel P. Berrange } 9953e308f20SDaniel P. Berrange 9963e308f20SDaniel P. Berrange 9973e308f20SDaniel P. Berrange /* 9983e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 9993e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 10003e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 10013e308f20SDaniel P. Berrange * 10023e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 10033e308f20SDaniel P. Berrange */ 10043e308f20SDaniel P. Berrange static int 10053e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 10063e308f20SDaniel P. Berrange const char *password, 10071ddd52e4SMaxim Levitsky uint8_t *masterkey, 10083e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 10093e308f20SDaniel P. Berrange void *opaque, 10103e308f20SDaniel P. Berrange Error **errp) 10113e308f20SDaniel P. Berrange { 10123e308f20SDaniel P. Berrange size_t i; 10133e308f20SDaniel P. Berrange int rv; 10143e308f20SDaniel P. Berrange 10153e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10163e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 10177e60a6f5SMaxim Levitsky i, 10183e308f20SDaniel P. Berrange password, 10191ddd52e4SMaxim Levitsky masterkey, 10203e308f20SDaniel P. Berrange readfunc, 10213e308f20SDaniel P. Berrange opaque, 10223e308f20SDaniel P. Berrange errp); 10233e308f20SDaniel P. Berrange if (rv < 0) { 10243e308f20SDaniel P. Berrange goto error; 10253e308f20SDaniel P. Berrange } 10263e308f20SDaniel P. Berrange if (rv == 1) { 10273e308f20SDaniel P. Berrange return 0; 10283e308f20SDaniel P. Berrange } 10293e308f20SDaniel P. Berrange } 10303e308f20SDaniel P. Berrange 10313e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 10323e308f20SDaniel P. Berrange error: 10333e308f20SDaniel P. Berrange return -1; 10343e308f20SDaniel P. Berrange } 10353e308f20SDaniel P. Berrange 1036557d2bdcSMaxim Levitsky /* 1037557d2bdcSMaxim Levitsky * Returns true if a slot i is marked as active 1038557d2bdcSMaxim Levitsky * (contains encrypted copy of the master key) 1039557d2bdcSMaxim Levitsky */ 1040557d2bdcSMaxim Levitsky static bool 1041557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, 1042557d2bdcSMaxim Levitsky unsigned int slot_idx) 1043557d2bdcSMaxim Levitsky { 1044557d2bdcSMaxim Levitsky uint32_t val; 1045557d2bdcSMaxim Levitsky 1046557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1047557d2bdcSMaxim Levitsky val = luks->header.key_slots[slot_idx].active; 1048557d2bdcSMaxim Levitsky return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1049557d2bdcSMaxim Levitsky } 1050557d2bdcSMaxim Levitsky 1051557d2bdcSMaxim Levitsky /* 1052557d2bdcSMaxim Levitsky * Returns the number of slots that are marked as active 1053557d2bdcSMaxim Levitsky * (slots that contain encrypted copy of the master key) 1054557d2bdcSMaxim Levitsky */ 1055557d2bdcSMaxim Levitsky static unsigned int 1056557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) 1057557d2bdcSMaxim Levitsky { 1058557d2bdcSMaxim Levitsky size_t i = 0; 1059557d2bdcSMaxim Levitsky unsigned int ret = 0; 1060557d2bdcSMaxim Levitsky 1061557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1062557d2bdcSMaxim Levitsky if (qcrypto_block_luks_slot_active(luks, i)) { 1063557d2bdcSMaxim Levitsky ret++; 1064557d2bdcSMaxim Levitsky } 1065557d2bdcSMaxim Levitsky } 1066557d2bdcSMaxim Levitsky return ret; 1067557d2bdcSMaxim Levitsky } 1068557d2bdcSMaxim Levitsky 1069557d2bdcSMaxim Levitsky /* 1070557d2bdcSMaxim Levitsky * Finds first key slot which is not active 1071557d2bdcSMaxim Levitsky * Returns the key slot index, or -1 if it doesn't exist 1072557d2bdcSMaxim Levitsky */ 1073557d2bdcSMaxim Levitsky static int 1074557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) 1075557d2bdcSMaxim Levitsky { 1076557d2bdcSMaxim Levitsky size_t i; 1077557d2bdcSMaxim Levitsky 1078557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1079557d2bdcSMaxim Levitsky if (!qcrypto_block_luks_slot_active(luks, i)) { 1080557d2bdcSMaxim Levitsky return i; 1081557d2bdcSMaxim Levitsky } 1082557d2bdcSMaxim Levitsky } 1083557d2bdcSMaxim Levitsky return -1; 1084557d2bdcSMaxim Levitsky } 1085557d2bdcSMaxim Levitsky 1086557d2bdcSMaxim Levitsky /* 1087557d2bdcSMaxim Levitsky * Erases an keyslot given its index 1088557d2bdcSMaxim Levitsky * Returns: 1089557d2bdcSMaxim Levitsky * 0 if the keyslot was erased successfully 1090557d2bdcSMaxim Levitsky * -1 if a error occurred while erasing the keyslot 1091557d2bdcSMaxim Levitsky * 1092557d2bdcSMaxim Levitsky */ 1093557d2bdcSMaxim Levitsky static int 1094557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block, 1095557d2bdcSMaxim Levitsky unsigned int slot_idx, 1096557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1097557d2bdcSMaxim Levitsky void *opaque, 1098557d2bdcSMaxim Levitsky Error **errp) 1099557d2bdcSMaxim Levitsky { 1100557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1101557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 1102557d2bdcSMaxim Levitsky g_autofree uint8_t *garbagesplitkey = NULL; 1103557d2bdcSMaxim Levitsky size_t splitkeylen; 1104557d2bdcSMaxim Levitsky size_t i; 1105557d2bdcSMaxim Levitsky Error *local_err = NULL; 1106557d2bdcSMaxim Levitsky int ret; 1107557d2bdcSMaxim Levitsky 1108557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1109557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 1110557d2bdcSMaxim Levitsky 1111557d2bdcSMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 1112557d2bdcSMaxim Levitsky assert(splitkeylen > 0); 1113557d2bdcSMaxim Levitsky 1114557d2bdcSMaxim Levitsky garbagesplitkey = g_new0(uint8_t, splitkeylen); 1115557d2bdcSMaxim Levitsky 1116557d2bdcSMaxim Levitsky /* Reset the key slot header */ 1117557d2bdcSMaxim Levitsky memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); 1118557d2bdcSMaxim Levitsky slot->iterations = 0; 1119557d2bdcSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 1120557d2bdcSMaxim Levitsky 1121557d2bdcSMaxim Levitsky ret = qcrypto_block_luks_store_header(block, writefunc, 1122557d2bdcSMaxim Levitsky opaque, &local_err); 1123557d2bdcSMaxim Levitsky 1124557d2bdcSMaxim Levitsky if (ret < 0) { 1125557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1126557d2bdcSMaxim Levitsky } 1127557d2bdcSMaxim Levitsky /* 1128557d2bdcSMaxim Levitsky * Now try to erase the key material, even if the header 1129557d2bdcSMaxim Levitsky * update failed 1130557d2bdcSMaxim Levitsky */ 1131557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { 1132557d2bdcSMaxim Levitsky if (qcrypto_random_bytes(garbagesplitkey, 1133557d2bdcSMaxim Levitsky splitkeylen, &local_err) < 0) { 1134557d2bdcSMaxim Levitsky /* 1135557d2bdcSMaxim Levitsky * If we failed to get the random data, still write 1136557d2bdcSMaxim Levitsky * at least zeros to the key slot at least once 1137557d2bdcSMaxim Levitsky */ 1138557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1139557d2bdcSMaxim Levitsky 1140557d2bdcSMaxim Levitsky if (i > 0) { 1141557d2bdcSMaxim Levitsky return -1; 1142557d2bdcSMaxim Levitsky } 1143557d2bdcSMaxim Levitsky } 1144557d2bdcSMaxim Levitsky if (writefunc(block, 1145557d2bdcSMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 1146557d2bdcSMaxim Levitsky garbagesplitkey, 1147557d2bdcSMaxim Levitsky splitkeylen, 1148557d2bdcSMaxim Levitsky opaque, 1149757dda54SAlberto Faria &local_err) < 0) { 1150557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1151557d2bdcSMaxim Levitsky return -1; 1152557d2bdcSMaxim Levitsky } 1153557d2bdcSMaxim Levitsky } 1154557d2bdcSMaxim Levitsky return ret; 1155557d2bdcSMaxim Levitsky } 11563e308f20SDaniel P. Berrange 11573e308f20SDaniel P. Berrange static int 11583e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 11593e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 11601cd9a787SDaniel P. Berrange const char *optprefix, 11613e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 11623e308f20SDaniel P. Berrange void *opaque, 11633e308f20SDaniel P. Berrange unsigned int flags, 1164c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 11653e308f20SDaniel P. Berrange Error **errp) 11663e308f20SDaniel P. Berrange { 11679d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 116857b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 116957b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 11703e308f20SDaniel P. Berrange 11713e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 11723e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 11731cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 11741cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 11753e308f20SDaniel P. Berrange return -1; 11763e308f20SDaniel P. Berrange } 11773e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 11783e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 11793e308f20SDaniel P. Berrange if (!password) { 11803e308f20SDaniel P. Berrange return -1; 11813e308f20SDaniel P. Berrange } 11823e308f20SDaniel P. Berrange } 11833e308f20SDaniel P. Berrange 11843e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 11853e308f20SDaniel P. Berrange block->opaque = luks; 1186557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 11873e308f20SDaniel P. Berrange 1188dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 11893e308f20SDaniel P. Berrange goto fail; 11903e308f20SDaniel P. Berrange } 11913e308f20SDaniel P. Berrange 11929fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_check_header(luks, errp) < 0) { 11933e308f20SDaniel P. Berrange goto fail; 11943e308f20SDaniel P. Berrange } 11953e308f20SDaniel P. Berrange 11969fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_parse_header(luks, errp) < 0) { 11973e308f20SDaniel P. Berrange goto fail; 11983e308f20SDaniel P. Berrange } 11993e308f20SDaniel P. Berrange 12003e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12013e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 12023e308f20SDaniel P. Berrange * and unlock the master key from that slot. 12033e308f20SDaniel P. Berrange */ 12041ddd52e4SMaxim Levitsky 12051ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 12061ddd52e4SMaxim Levitsky 12073e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 12083e308f20SDaniel P. Berrange password, 12091ddd52e4SMaxim Levitsky masterkey, 12103e308f20SDaniel P. Berrange readfunc, opaque, 12113e308f20SDaniel P. Berrange errp) < 0) { 12123e308f20SDaniel P. Berrange goto fail; 12133e308f20SDaniel P. Berrange } 12143e308f20SDaniel P. Berrange 12153e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 12163e308f20SDaniel P. Berrange * block device payload decryption objects 12173e308f20SDaniel P. Berrange */ 12189d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 12199d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 12209d80e59dSMaxim Levitsky luks->cipher_mode); 12219d80e59dSMaxim Levitsky 12229d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 12239d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 12249d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 12251ddd52e4SMaxim Levitsky masterkey, 12261ddd52e4SMaxim Levitsky luks->header.master_key_len, 12273e308f20SDaniel P. Berrange errp); 12283e308f20SDaniel P. Berrange if (!block->ivgen) { 12293e308f20SDaniel P. Berrange goto fail; 12303e308f20SDaniel P. Berrange } 12313e308f20SDaniel P. Berrange 123261dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 12339d80e59dSMaxim Levitsky luks->cipher_alg, 12349d80e59dSMaxim Levitsky luks->cipher_mode, 12351ddd52e4SMaxim Levitsky masterkey, 12361ddd52e4SMaxim Levitsky luks->header.master_key_len, 12371ddd52e4SMaxim Levitsky n_threads, 123861dd8a9aSMaxim Levitsky errp) < 0) { 12393e308f20SDaniel P. Berrange goto fail; 12403e308f20SDaniel P. Berrange } 12413e308f20SDaniel P. Berrange } 12423e308f20SDaniel P. Berrange 1243850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1244f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1245850f49deSDaniel P. Berrange block->sector_size; 12463e308f20SDaniel P. Berrange 12473e308f20SDaniel P. Berrange return 0; 12483e308f20SDaniel P. Berrange 12493e308f20SDaniel P. Berrange fail: 1250c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 12513e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 1252557d2bdcSMaxim Levitsky g_free(luks->secret); 12533e308f20SDaniel P. Berrange g_free(luks); 125461dd8a9aSMaxim Levitsky return -1; 12553e308f20SDaniel P. Berrange } 12563e308f20SDaniel P. Berrange 12573e308f20SDaniel P. Berrange 12582ef950f9SFam Zheng static void 12592ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 12603e308f20SDaniel P. Berrange { 12612ef950f9SFam Zheng QemuUUID uuid; 12622ef950f9SFam Zheng qemu_uuid_generate(&uuid); 12632ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 12643e308f20SDaniel P. Berrange } 12653e308f20SDaniel P. Berrange 12663e308f20SDaniel P. Berrange static int 12673e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 12683e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 12691cd9a787SDaniel P. Berrange const char *optprefix, 12703e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 12713e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 12723e308f20SDaniel P. Berrange void *opaque, 12733e308f20SDaniel P. Berrange Error **errp) 12743e308f20SDaniel P. Berrange { 12753e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 12763e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 12773e308f20SDaniel P. Berrange Error *local_err = NULL; 127857b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 1279bd56a55aSMaxim Levitsky size_t header_sectors; 1280bd56a55aSMaxim Levitsky size_t split_key_sectors; 12813e308f20SDaniel P. Berrange size_t i; 128257b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 12833e308f20SDaniel P. Berrange const char *cipher_alg; 12843e308f20SDaniel P. Berrange const char *cipher_mode; 12853e308f20SDaniel P. Berrange const char *ivgen_alg; 12863e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 12873e308f20SDaniel P. Berrange const char *hash_alg; 128857b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 128959b060beSDaniel P. Berrange uint64_t iters; 12903e308f20SDaniel P. Berrange 12913e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 12923bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 1293557d2bdcSMaxim Levitsky luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 12943bd18890SDaniel P. Berrange } 12953e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 12963e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 12973e308f20SDaniel P. Berrange } 12983e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 12993e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 13003e308f20SDaniel P. Berrange } 13013e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 13023e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 13033e308f20SDaniel P. Berrange } 13043e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 13053e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 13063e308f20SDaniel P. Berrange } 13078b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 13088b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 13098b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 13108b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 13118b7cdba3SDaniel P. Berrange } 13128b7cdba3SDaniel P. Berrange } 13139d80e59dSMaxim Levitsky 13149d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 13159d80e59dSMaxim Levitsky block->opaque = luks; 13169d80e59dSMaxim Levitsky 13179d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 13189d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 13199d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 13209d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 13219d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 13229d80e59dSMaxim Levitsky 13239d80e59dSMaxim Levitsky 13248b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 13258b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 13268b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 13273e308f20SDaniel P. Berrange 13283e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 13291cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 13301cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 13319d80e59dSMaxim Levitsky goto error; 13323e308f20SDaniel P. Berrange } 1333557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 1334557d2bdcSMaxim Levitsky 13353e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 13363e308f20SDaniel P. Berrange if (!password) { 13379d80e59dSMaxim Levitsky goto error; 13383e308f20SDaniel P. Berrange } 13393e308f20SDaniel P. Berrange 13403e308f20SDaniel P. Berrange 13413e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 13423e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 13433e308f20SDaniel P. Berrange 13443e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 13453e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 13463e308f20SDaniel P. Berrange * it out to disk 13473e308f20SDaniel P. Berrange */ 13483e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 13492ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 13503e308f20SDaniel P. Berrange 13513e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 13523e308f20SDaniel P. Berrange errp); 13533e308f20SDaniel P. Berrange if (!cipher_alg) { 13543e308f20SDaniel P. Berrange goto error; 13553e308f20SDaniel P. Berrange } 13563e308f20SDaniel P. Berrange 1357977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 1358977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 13593e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 1360977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 13613e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 13623e308f20SDaniel P. Berrange ivgen_hash_alg); 13633e308f20SDaniel P. Berrange } else { 13643e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 13653e308f20SDaniel P. Berrange } 1366977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 13673e308f20SDaniel P. Berrange 13683e308f20SDaniel P. Berrange 13693e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 13703e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 13713e308f20SDaniel P. Berrange cipher_alg); 13723e308f20SDaniel P. Berrange goto error; 13733e308f20SDaniel P. Berrange } 13743e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 13753e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 13763e308f20SDaniel P. Berrange cipher_mode_spec); 13773e308f20SDaniel P. Berrange goto error; 13783e308f20SDaniel P. Berrange } 13793e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 13803e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 13813e308f20SDaniel P. Berrange hash_alg); 13823e308f20SDaniel P. Berrange goto error; 13833e308f20SDaniel P. Berrange } 13843e308f20SDaniel P. Berrange 13853e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 13869d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 13879d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 13883e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 13893e308f20SDaniel P. Berrange &local_err); 13903e308f20SDaniel P. Berrange if (local_err) { 13913e308f20SDaniel P. Berrange error_propagate(errp, local_err); 13923e308f20SDaniel P. Berrange goto error; 13933e308f20SDaniel P. Berrange } 13943e308f20SDaniel P. Berrange } else { 13959d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 13963e308f20SDaniel P. Berrange } 13973e308f20SDaniel P. Berrange 13983e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 13993e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 14003e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 14013e308f20SDaniel P. Berrange 1402f0d3c362SMaxim Levitsky luks->header.master_key_len = 1403f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 1404f0d3c362SMaxim Levitsky 14053e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 1406f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 14073e308f20SDaniel P. Berrange } 14083e308f20SDaniel P. Berrange 14093e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 14103e308f20SDaniel P. Berrange * with PBKDF later 14113e308f20SDaniel P. Berrange */ 14123e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 14133e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 14143e308f20SDaniel P. Berrange errp) < 0) { 14153e308f20SDaniel P. Berrange goto error; 14163e308f20SDaniel P. Berrange } 14173e308f20SDaniel P. Berrange 14183e308f20SDaniel P. Berrange /* Generate random master key */ 1419f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 14203e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 1421f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 14223e308f20SDaniel P. Berrange goto error; 14233e308f20SDaniel P. Berrange } 14243e308f20SDaniel P. Berrange 14253e308f20SDaniel P. Berrange 14263e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1427c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1428c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1429f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 14303e308f20SDaniel P. Berrange goto error; 14313e308f20SDaniel P. Berrange } 14323e308f20SDaniel P. Berrange 14333e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 14343e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 14353e308f20SDaniel P. Berrange luks_opts.cipher_mode); 14363e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 14379d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 14383e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1439f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14403e308f20SDaniel P. Berrange errp); 14413e308f20SDaniel P. Berrange 14423e308f20SDaniel P. Berrange if (!block->ivgen) { 14433e308f20SDaniel P. Berrange goto error; 14443e308f20SDaniel P. Berrange } 14453e308f20SDaniel P. Berrange 14463e308f20SDaniel P. Berrange 14473e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 14483e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 14493e308f20SDaniel P. Berrange */ 145059b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1451f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14523e308f20SDaniel P. Berrange luks->header.master_key_salt, 14533e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1454e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 14553e308f20SDaniel P. Berrange &local_err); 14563e308f20SDaniel P. Berrange if (local_err) { 14573e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14583e308f20SDaniel P. Berrange goto error; 14593e308f20SDaniel P. Berrange } 14603e308f20SDaniel P. Berrange 14613bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 14623bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 14633bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 14643bd18890SDaniel P. Berrange (unsigned long long)iters); 14653bd18890SDaniel P. Berrange goto error; 14663bd18890SDaniel P. Berrange } 14673bd18890SDaniel P. Berrange 14683bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 14693bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 14703bd18890SDaniel P. Berrange 14713e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 14723e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 14733e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 14743e308f20SDaniel P. Berrange * in total time to check all keys */ 147559b060beSDaniel P. Berrange iters /= 8; 147659b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 147759b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 147859b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 147959b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 148059b060beSDaniel P. Berrange goto error; 148159b060beSDaniel P. Berrange } 148259b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 148359b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 14843e308f20SDaniel P. Berrange 14853e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 14863e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 14873e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 14883e308f20SDaniel P. Berrange * valid master key 14893e308f20SDaniel P. Berrange */ 14903e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1491f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14923e308f20SDaniel P. Berrange luks->header.master_key_salt, 14933e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 14943e308f20SDaniel P. Berrange luks->header.master_key_iterations, 14953e308f20SDaniel P. Berrange luks->header.master_key_digest, 14963e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 14973e308f20SDaniel P. Berrange errp) < 0) { 14983e308f20SDaniel P. Berrange goto error; 14993e308f20SDaniel P. Berrange } 15003e308f20SDaniel P. Berrange 1501bd56a55aSMaxim Levitsky /* start with the sector that follows the header*/ 1502bd56a55aSMaxim Levitsky header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 1503bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 15043e308f20SDaniel P. Berrange 1505bd56a55aSMaxim Levitsky split_key_sectors = 1506bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 1507bd56a55aSMaxim Levitsky header_sectors, 1508bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_STRIPES); 1509bd56a55aSMaxim Levitsky 15103e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1511bd56a55aSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i]; 1512bd56a55aSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 15133e308f20SDaniel P. Berrange 1514bd56a55aSMaxim Levitsky slot->key_offset_sector = header_sectors + i * split_key_sectors; 1515bd56a55aSMaxim Levitsky slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 15163e308f20SDaniel P. Berrange } 15173e308f20SDaniel P. Berrange 15183e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 15193e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 15203e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 15213e308f20SDaniel P. Berrange * to the nearest sector */ 1522bd56a55aSMaxim Levitsky luks->header.payload_offset_sector = header_sectors + 1523bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors; 15243e308f20SDaniel P. Berrange 1525850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1526f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1527850f49deSDaniel P. Berrange block->sector_size; 15283e308f20SDaniel P. Berrange 15293e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1530e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 15313e308f20SDaniel P. Berrange if (local_err) { 15323e308f20SDaniel P. Berrange error_propagate(errp, local_err); 15333e308f20SDaniel P. Berrange goto error; 15343e308f20SDaniel P. Berrange } 15353e308f20SDaniel P. Berrange 15363e308f20SDaniel P. Berrange 15373994a7c9SMaxim Levitsky /* populate the slot 0 with the password encrypted master key*/ 15383994a7c9SMaxim Levitsky /* This will also store the header */ 15393994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_key(block, 15403994a7c9SMaxim Levitsky 0, 15413994a7c9SMaxim Levitsky password, 15423994a7c9SMaxim Levitsky masterkey, 15433994a7c9SMaxim Levitsky luks_opts.iter_time, 15443994a7c9SMaxim Levitsky writefunc, 1545e4a3507eSDaniel P. Berrange opaque, 15463994a7c9SMaxim Levitsky errp) < 0) { 15473e308f20SDaniel P. Berrange goto error; 15483e308f20SDaniel P. Berrange } 15493e308f20SDaniel P. Berrange 1550f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15513e308f20SDaniel P. Berrange 15523e308f20SDaniel P. Berrange return 0; 15533e308f20SDaniel P. Berrange 15543e308f20SDaniel P. Berrange error: 15553e308f20SDaniel P. Berrange if (masterkey) { 1556f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15573e308f20SDaniel P. Berrange } 15583e308f20SDaniel P. Berrange 1559c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1560b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1561b640adcaSVladimir Sementsov-Ogievskiy 1562557d2bdcSMaxim Levitsky g_free(luks->secret); 15633e308f20SDaniel P. Berrange g_free(luks); 15643e308f20SDaniel P. Berrange return -1; 15653e308f20SDaniel P. Berrange } 15663e308f20SDaniel P. Berrange 1567557d2bdcSMaxim Levitsky static int 1568557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, 1569557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1570557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1571557d2bdcSMaxim Levitsky void *opaque, 1572557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1573557d2bdcSMaxim Levitsky bool force, 1574557d2bdcSMaxim Levitsky Error **errp) 1575557d2bdcSMaxim Levitsky { 1576557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1577557d2bdcSMaxim Levitsky uint64_t iter_time = opts_luks->has_iter_time ? 1578557d2bdcSMaxim Levitsky opts_luks->iter_time : 1579557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1580557d2bdcSMaxim Levitsky int keyslot; 1581557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1582557d2bdcSMaxim Levitsky g_autofree char *new_password = NULL; 1583557d2bdcSMaxim Levitsky g_autofree uint8_t *master_key = NULL; 1584557d2bdcSMaxim Levitsky 1585557d2bdcSMaxim Levitsky char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret; 1586557d2bdcSMaxim Levitsky 1587557d2bdcSMaxim Levitsky if (!opts_luks->has_new_secret) { 1588557d2bdcSMaxim Levitsky error_setg(errp, "'new-secret' is required to activate a keyslot"); 1589557d2bdcSMaxim Levitsky return -1; 1590557d2bdcSMaxim Levitsky } 1591557d2bdcSMaxim Levitsky if (opts_luks->has_old_secret) { 1592557d2bdcSMaxim Levitsky error_setg(errp, 1593557d2bdcSMaxim Levitsky "'old-secret' must not be given when activating keyslots"); 1594557d2bdcSMaxim Levitsky return -1; 1595557d2bdcSMaxim Levitsky } 1596557d2bdcSMaxim Levitsky 1597557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1598557d2bdcSMaxim Levitsky keyslot = opts_luks->keyslot; 1599557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1600557d2bdcSMaxim Levitsky error_setg(errp, 1601557d2bdcSMaxim Levitsky "Invalid keyslot %u specified, must be between 0 and %u", 1602557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1603557d2bdcSMaxim Levitsky return -1; 1604557d2bdcSMaxim Levitsky } 1605557d2bdcSMaxim Levitsky } else { 1606557d2bdcSMaxim Levitsky keyslot = qcrypto_block_luks_find_free_keyslot(luks); 1607557d2bdcSMaxim Levitsky if (keyslot == -1) { 1608557d2bdcSMaxim Levitsky error_setg(errp, 1609557d2bdcSMaxim Levitsky "Can't add a keyslot - all keyslots are in use"); 1610557d2bdcSMaxim Levitsky return -1; 1611557d2bdcSMaxim Levitsky } 1612557d2bdcSMaxim Levitsky } 1613557d2bdcSMaxim Levitsky 1614557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { 1615557d2bdcSMaxim Levitsky error_setg(errp, 1616557d2bdcSMaxim Levitsky "Refusing to overwrite active keyslot %i - " 1617557d2bdcSMaxim Levitsky "please erase it first", 1618557d2bdcSMaxim Levitsky keyslot); 1619557d2bdcSMaxim Levitsky return -1; 1620557d2bdcSMaxim Levitsky } 1621557d2bdcSMaxim Levitsky 1622557d2bdcSMaxim Levitsky /* Locate the password that will be used to retrieve the master key */ 1623557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(secret, errp); 1624557d2bdcSMaxim Levitsky if (!old_password) { 1625557d2bdcSMaxim Levitsky return -1; 1626557d2bdcSMaxim Levitsky } 1627557d2bdcSMaxim Levitsky 1628557d2bdcSMaxim Levitsky /* Retrieve the master key */ 1629557d2bdcSMaxim Levitsky master_key = g_new0(uint8_t, luks->header.master_key_len); 1630557d2bdcSMaxim Levitsky 1631557d2bdcSMaxim Levitsky if (qcrypto_block_luks_find_key(block, old_password, master_key, 1632557d2bdcSMaxim Levitsky readfunc, opaque, errp) < 0) { 1633557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to retrieve the master key"); 1634557d2bdcSMaxim Levitsky return -1; 1635557d2bdcSMaxim Levitsky } 1636557d2bdcSMaxim Levitsky 1637557d2bdcSMaxim Levitsky /* Locate the new password*/ 1638557d2bdcSMaxim Levitsky new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); 1639557d2bdcSMaxim Levitsky if (!new_password) { 1640557d2bdcSMaxim Levitsky return -1; 1641557d2bdcSMaxim Levitsky } 1642557d2bdcSMaxim Levitsky 1643557d2bdcSMaxim Levitsky /* Now set the new keyslots */ 1644557d2bdcSMaxim Levitsky if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, 1645557d2bdcSMaxim Levitsky iter_time, writefunc, opaque, errp)) { 1646557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to write to keyslot %i", keyslot); 1647557d2bdcSMaxim Levitsky return -1; 1648557d2bdcSMaxim Levitsky } 1649557d2bdcSMaxim Levitsky return 0; 1650557d2bdcSMaxim Levitsky } 1651557d2bdcSMaxim Levitsky 1652557d2bdcSMaxim Levitsky static int 1653557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, 1654557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1655557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1656557d2bdcSMaxim Levitsky void *opaque, 1657557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1658557d2bdcSMaxim Levitsky bool force, 1659557d2bdcSMaxim Levitsky Error **errp) 1660557d2bdcSMaxim Levitsky { 1661557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1662557d2bdcSMaxim Levitsky g_autofree uint8_t *tmpkey = NULL; 1663557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1664557d2bdcSMaxim Levitsky 1665557d2bdcSMaxim Levitsky if (opts_luks->has_new_secret) { 1666557d2bdcSMaxim Levitsky error_setg(errp, 1667557d2bdcSMaxim Levitsky "'new-secret' must not be given when erasing keyslots"); 1668557d2bdcSMaxim Levitsky return -1; 1669557d2bdcSMaxim Levitsky } 1670557d2bdcSMaxim Levitsky if (opts_luks->has_iter_time) { 1671557d2bdcSMaxim Levitsky error_setg(errp, 1672557d2bdcSMaxim Levitsky "'iter-time' must not be given when erasing keyslots"); 1673557d2bdcSMaxim Levitsky return -1; 1674557d2bdcSMaxim Levitsky } 1675557d2bdcSMaxim Levitsky if (opts_luks->has_secret) { 1676557d2bdcSMaxim Levitsky error_setg(errp, 1677557d2bdcSMaxim Levitsky "'secret' must not be given when erasing keyslots"); 1678557d2bdcSMaxim Levitsky return -1; 1679557d2bdcSMaxim Levitsky } 1680557d2bdcSMaxim Levitsky 1681557d2bdcSMaxim Levitsky /* Load the old password if given */ 1682557d2bdcSMaxim Levitsky if (opts_luks->has_old_secret) { 1683557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, 1684557d2bdcSMaxim Levitsky errp); 1685557d2bdcSMaxim Levitsky if (!old_password) { 1686557d2bdcSMaxim Levitsky return -1; 1687557d2bdcSMaxim Levitsky } 1688557d2bdcSMaxim Levitsky 1689557d2bdcSMaxim Levitsky /* 1690557d2bdcSMaxim Levitsky * Allocate a temporary key buffer that we will need when 1691557d2bdcSMaxim Levitsky * checking if slot matches the given old password 1692557d2bdcSMaxim Levitsky */ 1693557d2bdcSMaxim Levitsky tmpkey = g_new0(uint8_t, luks->header.master_key_len); 1694557d2bdcSMaxim Levitsky } 1695557d2bdcSMaxim Levitsky 1696557d2bdcSMaxim Levitsky /* Erase an explicitly given keyslot */ 1697557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1698557d2bdcSMaxim Levitsky int keyslot = opts_luks->keyslot; 1699557d2bdcSMaxim Levitsky 1700557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1701557d2bdcSMaxim Levitsky error_setg(errp, 1702557d2bdcSMaxim Levitsky "Invalid keyslot %i specified, must be between 0 and %i", 1703557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1704557d2bdcSMaxim Levitsky return -1; 1705557d2bdcSMaxim Levitsky } 1706557d2bdcSMaxim Levitsky 1707557d2bdcSMaxim Levitsky if (opts_luks->has_old_secret) { 1708557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1709557d2bdcSMaxim Levitsky keyslot, 1710557d2bdcSMaxim Levitsky old_password, 1711557d2bdcSMaxim Levitsky tmpkey, 1712557d2bdcSMaxim Levitsky readfunc, 1713557d2bdcSMaxim Levitsky opaque, 1714557d2bdcSMaxim Levitsky errp); 1715557d2bdcSMaxim Levitsky if (rv == -1) { 1716557d2bdcSMaxim Levitsky return -1; 1717557d2bdcSMaxim Levitsky } else if (rv == 0) { 1718557d2bdcSMaxim Levitsky error_setg(errp, 1719557d2bdcSMaxim Levitsky "Given keyslot %i doesn't contain the given " 1720557d2bdcSMaxim Levitsky "old password for erase operation", 1721557d2bdcSMaxim Levitsky keyslot); 1722557d2bdcSMaxim Levitsky return -1; 1723557d2bdcSMaxim Levitsky } 1724557d2bdcSMaxim Levitsky } 1725557d2bdcSMaxim Levitsky 1726557d2bdcSMaxim Levitsky if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { 1727557d2bdcSMaxim Levitsky error_setg(errp, 1728557d2bdcSMaxim Levitsky "Given keyslot %i is already erased (inactive) ", 1729557d2bdcSMaxim Levitsky keyslot); 1730557d2bdcSMaxim Levitsky return -1; 1731557d2bdcSMaxim Levitsky } 1732557d2bdcSMaxim Levitsky 1733557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { 1734557d2bdcSMaxim Levitsky error_setg(errp, 1735557d2bdcSMaxim Levitsky "Attempt to erase the only active keyslot %i " 1736557d2bdcSMaxim Levitsky "which will erase all the data in the image " 1737557d2bdcSMaxim Levitsky "irreversibly - refusing operation", 1738557d2bdcSMaxim Levitsky keyslot); 1739557d2bdcSMaxim Levitsky return -1; 1740557d2bdcSMaxim Levitsky } 1741557d2bdcSMaxim Levitsky 1742557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, keyslot, 1743557d2bdcSMaxim Levitsky writefunc, opaque, errp)) { 1744557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %i", keyslot); 1745557d2bdcSMaxim Levitsky return -1; 1746557d2bdcSMaxim Levitsky } 1747557d2bdcSMaxim Levitsky 1748557d2bdcSMaxim Levitsky /* Erase all keyslots that match the given old password */ 1749557d2bdcSMaxim Levitsky } else if (opts_luks->has_old_secret) { 1750557d2bdcSMaxim Levitsky 1751557d2bdcSMaxim Levitsky unsigned long slots_to_erase_bitmap = 0; 1752557d2bdcSMaxim Levitsky size_t i; 1753557d2bdcSMaxim Levitsky int slot_count; 1754557d2bdcSMaxim Levitsky 1755557d2bdcSMaxim Levitsky assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= 1756557d2bdcSMaxim Levitsky sizeof(slots_to_erase_bitmap) * 8); 1757557d2bdcSMaxim Levitsky 1758557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1759557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1760557d2bdcSMaxim Levitsky i, 1761557d2bdcSMaxim Levitsky old_password, 1762557d2bdcSMaxim Levitsky tmpkey, 1763557d2bdcSMaxim Levitsky readfunc, 1764557d2bdcSMaxim Levitsky opaque, 1765557d2bdcSMaxim Levitsky errp); 1766557d2bdcSMaxim Levitsky if (rv == -1) { 1767557d2bdcSMaxim Levitsky return -1; 1768557d2bdcSMaxim Levitsky } else if (rv == 1) { 1769557d2bdcSMaxim Levitsky bitmap_set(&slots_to_erase_bitmap, i, 1); 1770557d2bdcSMaxim Levitsky } 1771557d2bdcSMaxim Levitsky } 1772557d2bdcSMaxim Levitsky 1773557d2bdcSMaxim Levitsky slot_count = bitmap_count_one(&slots_to_erase_bitmap, 1774557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1775557d2bdcSMaxim Levitsky if (slot_count == 0) { 1776557d2bdcSMaxim Levitsky error_setg(errp, 1777557d2bdcSMaxim Levitsky "No keyslots match given (old) password for erase operation"); 1778557d2bdcSMaxim Levitsky return -1; 1779557d2bdcSMaxim Levitsky } 1780557d2bdcSMaxim Levitsky 1781557d2bdcSMaxim Levitsky if (!force && 1782557d2bdcSMaxim Levitsky slot_count == qcrypto_block_luks_count_active_slots(luks)) { 1783557d2bdcSMaxim Levitsky error_setg(errp, 1784557d2bdcSMaxim Levitsky "All the active keyslots match the (old) password that " 1785557d2bdcSMaxim Levitsky "was given and erasing them will erase all the data in " 1786557d2bdcSMaxim Levitsky "the image irreversibly - refusing operation"); 1787557d2bdcSMaxim Levitsky return -1; 1788557d2bdcSMaxim Levitsky } 1789557d2bdcSMaxim Levitsky 1790557d2bdcSMaxim Levitsky /* Now apply the update */ 1791557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1792557d2bdcSMaxim Levitsky if (!test_bit(i, &slots_to_erase_bitmap)) { 1793557d2bdcSMaxim Levitsky continue; 1794557d2bdcSMaxim Levitsky } 1795557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, i, writefunc, 1796557d2bdcSMaxim Levitsky opaque, errp)) { 1797557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %zu", i); 1798557d2bdcSMaxim Levitsky return -1; 1799557d2bdcSMaxim Levitsky } 1800557d2bdcSMaxim Levitsky } 1801557d2bdcSMaxim Levitsky } else { 1802557d2bdcSMaxim Levitsky error_setg(errp, 1803557d2bdcSMaxim Levitsky "To erase keyslot(s), either explicit keyslot index " 1804557d2bdcSMaxim Levitsky "or the password currently contained in them must be given"); 1805557d2bdcSMaxim Levitsky return -1; 1806557d2bdcSMaxim Levitsky } 1807557d2bdcSMaxim Levitsky return 0; 1808557d2bdcSMaxim Levitsky } 1809557d2bdcSMaxim Levitsky 1810557d2bdcSMaxim Levitsky static int 1811557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block, 1812557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1813557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1814557d2bdcSMaxim Levitsky void *opaque, 1815557d2bdcSMaxim Levitsky QCryptoBlockAmendOptions *options, 1816557d2bdcSMaxim Levitsky bool force, 1817557d2bdcSMaxim Levitsky Error **errp) 1818557d2bdcSMaxim Levitsky { 1819557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; 1820557d2bdcSMaxim Levitsky 1821557d2bdcSMaxim Levitsky switch (opts_luks->state) { 1822557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: 1823557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_add_keyslot(block, readfunc, 1824557d2bdcSMaxim Levitsky writefunc, opaque, 1825557d2bdcSMaxim Levitsky opts_luks, force, errp); 1826557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: 1827557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, 1828557d2bdcSMaxim Levitsky writefunc, opaque, 1829557d2bdcSMaxim Levitsky opts_luks, force, errp); 1830557d2bdcSMaxim Levitsky default: 1831557d2bdcSMaxim Levitsky g_assert_not_reached(); 1832557d2bdcSMaxim Levitsky } 1833557d2bdcSMaxim Levitsky } 18343e308f20SDaniel P. Berrange 183540c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 183640c85028SDaniel P. Berrange QCryptoBlockInfo *info, 183740c85028SDaniel P. Berrange Error **errp) 183840c85028SDaniel P. Berrange { 183940c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 184040c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 1841c3033fd3SEric Blake QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots; 184240c85028SDaniel P. Berrange size_t i; 184340c85028SDaniel P. Berrange 184440c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 184540c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 184640c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 184740c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 184840c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 184940c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 185040c85028SDaniel P. Berrange } 185140c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 185240c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 185340c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 185440c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 185540c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 185640c85028SDaniel P. Berrange 185740c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1858c3033fd3SEric Blake slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 185940c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 186040c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1861f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 186240c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 186340c85028SDaniel P. Berrange if (slot->active) { 186440c85028SDaniel P. Berrange slot->has_iters = true; 186540c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 186640c85028SDaniel P. Berrange slot->has_stripes = true; 186740c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 186840c85028SDaniel P. Berrange } 186940c85028SDaniel P. Berrange 1870c3033fd3SEric Blake QAPI_LIST_APPEND(tail, slot); 187140c85028SDaniel P. Berrange } 187240c85028SDaniel P. Berrange 187340c85028SDaniel P. Berrange return 0; 187440c85028SDaniel P. Berrange } 187540c85028SDaniel P. Berrange 187640c85028SDaniel P. Berrange 18773e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 18783e308f20SDaniel P. Berrange { 1879557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1880557d2bdcSMaxim Levitsky if (luks) { 1881557d2bdcSMaxim Levitsky g_free(luks->secret); 1882557d2bdcSMaxim Levitsky g_free(luks); 1883557d2bdcSMaxim Levitsky } 18843e308f20SDaniel P. Berrange } 18853e308f20SDaniel P. Berrange 18863e308f20SDaniel P. Berrange 18873e308f20SDaniel P. Berrange static int 18883e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 18894609742aSDaniel P. Berrange uint64_t offset, 18903e308f20SDaniel P. Berrange uint8_t *buf, 18913e308f20SDaniel P. Berrange size_t len, 18923e308f20SDaniel P. Berrange Error **errp) 18933e308f20SDaniel P. Berrange { 18944609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 18954609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 18960f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 18973e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 18984609742aSDaniel P. Berrange offset, buf, len, errp); 18993e308f20SDaniel P. Berrange } 19003e308f20SDaniel P. Berrange 19013e308f20SDaniel P. Berrange 19023e308f20SDaniel P. Berrange static int 19033e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 19044609742aSDaniel P. Berrange uint64_t offset, 19053e308f20SDaniel P. Berrange uint8_t *buf, 19063e308f20SDaniel P. Berrange size_t len, 19073e308f20SDaniel P. Berrange Error **errp) 19083e308f20SDaniel P. Berrange { 19094609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19104609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19110f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 19123e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19134609742aSDaniel P. Berrange offset, buf, len, errp); 19143e308f20SDaniel P. Berrange } 19153e308f20SDaniel P. Berrange 19163e308f20SDaniel P. Berrange 19173e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 19183e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 19193e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 1920557d2bdcSMaxim Levitsky .amend = qcrypto_block_luks_amend_options, 192140c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 19223e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 19233e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 19243e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 19253e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 19263e308f20SDaniel P. Berrange }; 1927