13e308f20SDaniel P. Berrange /* 23e308f20SDaniel P. Berrange * QEMU Crypto block device encryption LUKS format 33e308f20SDaniel P. Berrange * 43e308f20SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 53e308f20SDaniel P. Berrange * 63e308f20SDaniel P. Berrange * This library is free software; you can redistribute it and/or 73e308f20SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 83e308f20SDaniel P. Berrange * License as published by the Free Software Foundation; either 9b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 103e308f20SDaniel P. Berrange * 113e308f20SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 123e308f20SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 133e308f20SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143e308f20SDaniel P. Berrange * Lesser General Public License for more details. 153e308f20SDaniel P. Berrange * 163e308f20SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 173e308f20SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 183e308f20SDaniel P. Berrange * 193e308f20SDaniel P. Berrange */ 203e308f20SDaniel P. Berrange 213e308f20SDaniel P. Berrange #include "qemu/osdep.h" 22da34e65cSMarkus Armbruster #include "qapi/error.h" 2358369e22SPaolo Bonzini #include "qemu/bswap.h" 243e308f20SDaniel P. Berrange 25986bc8deSMichael S. Tsirkin #include "block-luks.h" 2636445aceSDaniel P. Berrangé #include "block-luks-priv.h" 273e308f20SDaniel P. Berrange 283e308f20SDaniel P. Berrange #include "crypto/hash.h" 293e308f20SDaniel P. Berrange #include "crypto/afsplit.h" 303e308f20SDaniel P. Berrange #include "crypto/pbkdf.h" 313e308f20SDaniel P. Berrange #include "crypto/secret.h" 323e308f20SDaniel P. Berrange #include "crypto/random.h" 332ef950f9SFam Zheng #include "qemu/uuid.h" 343e308f20SDaniel P. Berrange 35557d2bdcSMaxim Levitsky #include "qemu/bitmap.h" 363e308f20SDaniel P. Berrange 373e308f20SDaniel P. Berrange /* 383e308f20SDaniel P. Berrange * Reference for the LUKS format implemented here is 393e308f20SDaniel P. Berrange * 403e308f20SDaniel P. Berrange * docs/on-disk-format.pdf 413e308f20SDaniel P. Berrange * 423e308f20SDaniel P. Berrange * in 'cryptsetup' package source code 433e308f20SDaniel P. Berrange * 443e308f20SDaniel P. Berrange * This file implements the 1.2.1 specification, dated 453e308f20SDaniel P. Berrange * Oct 16, 2011. 463e308f20SDaniel P. Berrange */ 473e308f20SDaniel P. Berrange 483e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKS QCryptoBlockLUKS; 493e308f20SDaniel P. Berrange 503e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSNameMap QCryptoBlockLUKSNameMap; 513e308f20SDaniel P. Berrange struct QCryptoBlockLUKSNameMap { 523e308f20SDaniel P. Berrange const char *name; 533e308f20SDaniel P. Berrange int id; 543e308f20SDaniel P. Berrange }; 553e308f20SDaniel P. Berrange 563e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherSizeMap QCryptoBlockLUKSCipherSizeMap; 573e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherSizeMap { 583e308f20SDaniel P. Berrange uint32_t key_bytes; 593e308f20SDaniel P. Berrange int id; 603e308f20SDaniel P. Berrange }; 613e308f20SDaniel P. Berrange typedef struct QCryptoBlockLUKSCipherNameMap QCryptoBlockLUKSCipherNameMap; 623e308f20SDaniel P. Berrange struct QCryptoBlockLUKSCipherNameMap { 633e308f20SDaniel P. Berrange const char *name; 643e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherSizeMap *sizes; 653e308f20SDaniel P. Berrange }; 663e308f20SDaniel P. Berrange 673e308f20SDaniel P. Berrange 683e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 693e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_aes[] = { 703e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_AES_128 }, 713e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_AES_192 }, 723e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_AES_256 }, 733e308f20SDaniel P. Berrange { 0, 0 }, 743e308f20SDaniel P. Berrange }; 753e308f20SDaniel P. Berrange 763e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 773e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_cast5[] = { 783e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_CAST5_128 }, 793e308f20SDaniel P. Berrange { 0, 0 }, 803e308f20SDaniel P. Berrange }; 813e308f20SDaniel P. Berrange 823e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 833e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_serpent[] = { 843e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_SERPENT_128 }, 853e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_SERPENT_192 }, 863e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_SERPENT_256 }, 873e308f20SDaniel P. Berrange { 0, 0 }, 883e308f20SDaniel P. Berrange }; 893e308f20SDaniel P. Berrange 903e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherSizeMap 913e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_size_map_twofish[] = { 923e308f20SDaniel P. Berrange { 16, QCRYPTO_CIPHER_ALG_TWOFISH_128 }, 933e308f20SDaniel P. Berrange { 24, QCRYPTO_CIPHER_ALG_TWOFISH_192 }, 943e308f20SDaniel P. Berrange { 32, QCRYPTO_CIPHER_ALG_TWOFISH_256 }, 953e308f20SDaniel P. Berrange { 0, 0 }, 963e308f20SDaniel P. Berrange }; 973e308f20SDaniel P. Berrange 983e308f20SDaniel P. Berrange static const QCryptoBlockLUKSCipherNameMap 993e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map[] = { 1003e308f20SDaniel P. Berrange { "aes", qcrypto_block_luks_cipher_size_map_aes }, 1013e308f20SDaniel P. Berrange { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, 1023e308f20SDaniel P. Berrange { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, 1033e308f20SDaniel P. Berrange { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, 1043e308f20SDaniel P. Berrange }; 1053e308f20SDaniel P. Berrange 1063e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48); 1073e308f20SDaniel P. Berrange QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) != 592); 1083e308f20SDaniel P. Berrange 1093e308f20SDaniel P. Berrange 1103e308f20SDaniel P. Berrange struct QCryptoBlockLUKS { 1113e308f20SDaniel P. Berrange QCryptoBlockLUKSHeader header; 11240c85028SDaniel P. Berrange 1139d80e59dSMaxim Levitsky /* Main encryption algorithm used for encryption*/ 11440c85028SDaniel P. Berrange QCryptoCipherAlgorithm cipher_alg; 1159d80e59dSMaxim Levitsky 1169d80e59dSMaxim Levitsky /* Mode of encryption for the selected encryption algorithm */ 11740c85028SDaniel P. Berrange QCryptoCipherMode cipher_mode; 1189d80e59dSMaxim Levitsky 1199d80e59dSMaxim Levitsky /* Initialization vector generation algorithm */ 12040c85028SDaniel P. Berrange QCryptoIVGenAlgorithm ivgen_alg; 1219d80e59dSMaxim Levitsky 1229d80e59dSMaxim Levitsky /* Hash algorithm used for IV generation*/ 12340c85028SDaniel P. Berrange QCryptoHashAlgorithm ivgen_hash_alg; 1249d80e59dSMaxim Levitsky 1259d80e59dSMaxim Levitsky /* 1269d80e59dSMaxim Levitsky * Encryption algorithm used for IV generation. 1279d80e59dSMaxim Levitsky * Usually the same as main encryption algorithm 1289d80e59dSMaxim Levitsky */ 1299d80e59dSMaxim Levitsky QCryptoCipherAlgorithm ivgen_cipher_alg; 1309d80e59dSMaxim Levitsky 1319d80e59dSMaxim Levitsky /* Hash algorithm used in pbkdf2 function */ 13240c85028SDaniel P. Berrange QCryptoHashAlgorithm hash_alg; 133557d2bdcSMaxim Levitsky 134557d2bdcSMaxim Levitsky /* Name of the secret that was used to open the image */ 135557d2bdcSMaxim Levitsky char *secret; 1363e308f20SDaniel P. Berrange }; 1373e308f20SDaniel P. Berrange 1383e308f20SDaniel P. Berrange 1393e308f20SDaniel P. Berrange static int qcrypto_block_luks_cipher_name_lookup(const char *name, 1403e308f20SDaniel P. Berrange QCryptoCipherMode mode, 1413e308f20SDaniel P. Berrange uint32_t key_bytes, 1423e308f20SDaniel P. Berrange Error **errp) 1433e308f20SDaniel P. Berrange { 1443e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 1453e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 1463e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 1473e308f20SDaniel P. Berrange size_t i, j; 1483e308f20SDaniel P. Berrange 1493e308f20SDaniel P. Berrange if (mode == QCRYPTO_CIPHER_MODE_XTS) { 1503e308f20SDaniel P. Berrange key_bytes /= 2; 1513e308f20SDaniel P. Berrange } 1523e308f20SDaniel P. Berrange 1533e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 1543e308f20SDaniel P. Berrange if (!g_str_equal(map[i].name, name)) { 1553e308f20SDaniel P. Berrange continue; 1563e308f20SDaniel P. Berrange } 1573e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 1583e308f20SDaniel P. Berrange if (map[i].sizes[j].key_bytes == key_bytes) { 1593e308f20SDaniel P. Berrange return map[i].sizes[j].id; 1603e308f20SDaniel P. Berrange } 1613e308f20SDaniel P. Berrange } 1623e308f20SDaniel P. Berrange } 1633e308f20SDaniel P. Berrange 1646c198932SDaniel P. Berrangé error_setg(errp, "Algorithm '%s' with key size %d bytes not supported", 1653e308f20SDaniel P. Berrange name, key_bytes); 1663e308f20SDaniel P. Berrange return 0; 1673e308f20SDaniel P. Berrange } 1683e308f20SDaniel P. Berrange 1693e308f20SDaniel P. Berrange static const char * 1703e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_alg_lookup(QCryptoCipherAlgorithm alg, 1713e308f20SDaniel P. Berrange Error **errp) 1723e308f20SDaniel P. Berrange { 1733e308f20SDaniel P. Berrange const QCryptoBlockLUKSCipherNameMap *map = 1743e308f20SDaniel P. Berrange qcrypto_block_luks_cipher_name_map; 1753e308f20SDaniel P. Berrange size_t maplen = G_N_ELEMENTS(qcrypto_block_luks_cipher_name_map); 1763e308f20SDaniel P. Berrange size_t i, j; 1773e308f20SDaniel P. Berrange for (i = 0; i < maplen; i++) { 1783e308f20SDaniel P. Berrange for (j = 0; j < map[i].sizes[j].key_bytes; j++) { 1793e308f20SDaniel P. Berrange if (map[i].sizes[j].id == alg) { 1803e308f20SDaniel P. Berrange return map[i].name; 1813e308f20SDaniel P. Berrange } 1823e308f20SDaniel P. Berrange } 1833e308f20SDaniel P. Berrange } 1843e308f20SDaniel P. Berrange 1853e308f20SDaniel P. Berrange error_setg(errp, "Algorithm '%s' not supported", 186977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(alg)); 1873e308f20SDaniel P. Berrange return NULL; 1883e308f20SDaniel P. Berrange } 1893e308f20SDaniel P. Berrange 1903e308f20SDaniel P. Berrange /* XXX replace with qapi_enum_parse() in future, when we can 1913e308f20SDaniel P. Berrange * make that function emit a more friendly error message */ 1923e308f20SDaniel P. Berrange static int qcrypto_block_luks_name_lookup(const char *name, 193f7abe0ecSMarc-André Lureau const QEnumLookup *map, 1943e308f20SDaniel P. Berrange const char *type, 1953e308f20SDaniel P. Berrange Error **errp) 1963e308f20SDaniel P. Berrange { 1979ae33079SMarkus Armbruster int ret = qapi_enum_parse(map, name, -1, NULL); 1983e308f20SDaniel P. Berrange 1999ae33079SMarkus Armbruster if (ret < 0) { 2006c198932SDaniel P. Berrangé error_setg(errp, "%s '%s' not supported", type, name); 2013e308f20SDaniel P. Berrange return 0; 2023e308f20SDaniel P. Berrange } 2039ae33079SMarkus Armbruster return ret; 2049ae33079SMarkus Armbruster } 2053e308f20SDaniel P. Berrange 2063e308f20SDaniel P. Berrange #define qcrypto_block_luks_cipher_mode_lookup(name, errp) \ 2073e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 208f7abe0ecSMarc-André Lureau &QCryptoCipherMode_lookup, \ 2093e308f20SDaniel P. Berrange "Cipher mode", \ 2103e308f20SDaniel P. Berrange errp) 2113e308f20SDaniel P. Berrange 2123e308f20SDaniel P. Berrange #define qcrypto_block_luks_hash_name_lookup(name, errp) \ 2133e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 214f7abe0ecSMarc-André Lureau &QCryptoHashAlgorithm_lookup, \ 2153e308f20SDaniel P. Berrange "Hash algorithm", \ 2163e308f20SDaniel P. Berrange errp) 2173e308f20SDaniel P. Berrange 2183e308f20SDaniel P. Berrange #define qcrypto_block_luks_ivgen_name_lookup(name, errp) \ 2193e308f20SDaniel P. Berrange qcrypto_block_luks_name_lookup(name, \ 220f7abe0ecSMarc-André Lureau &QCryptoIVGenAlgorithm_lookup, \ 2213e308f20SDaniel P. Berrange "IV generator", \ 2223e308f20SDaniel P. Berrange errp) 2233e308f20SDaniel P. Berrange 2243e308f20SDaniel P. Berrange 2253e308f20SDaniel P. Berrange static bool 2263e308f20SDaniel P. Berrange qcrypto_block_luks_has_format(const uint8_t *buf, 2273e308f20SDaniel P. Berrange size_t buf_size) 2283e308f20SDaniel P. Berrange { 2293e308f20SDaniel P. Berrange const QCryptoBlockLUKSHeader *luks_header = (const void *)buf; 2303e308f20SDaniel P. Berrange 2313e308f20SDaniel P. Berrange if (buf_size >= offsetof(QCryptoBlockLUKSHeader, cipher_name) && 2323e308f20SDaniel P. Berrange memcmp(luks_header->magic, qcrypto_block_luks_magic, 2333e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN) == 0 && 2343e308f20SDaniel P. Berrange be16_to_cpu(luks_header->version) == QCRYPTO_BLOCK_LUKS_VERSION) { 2353e308f20SDaniel P. Berrange return true; 2363e308f20SDaniel P. Berrange } else { 2373e308f20SDaniel P. Berrange return false; 2383e308f20SDaniel P. Berrange } 2393e308f20SDaniel P. Berrange } 2403e308f20SDaniel P. Berrange 2413e308f20SDaniel P. Berrange 2423e308f20SDaniel P. Berrange /** 2433e308f20SDaniel P. Berrange * Deal with a quirk of dm-crypt usage of ESSIV. 2443e308f20SDaniel P. Berrange * 2453e308f20SDaniel P. Berrange * When calculating ESSIV IVs, the cipher length used by ESSIV 2463e308f20SDaniel P. Berrange * may be different from the cipher length used for the block 2473e308f20SDaniel P. Berrange * encryption, becauses dm-crypt uses the hash digest length 2483e308f20SDaniel P. Berrange * as the key size. ie, if you have AES 128 as the block cipher 2493e308f20SDaniel P. Berrange * and SHA 256 as ESSIV hash, then ESSIV will use AES 256 as 2503e308f20SDaniel P. Berrange * the cipher since that gets a key length matching the digest 2513e308f20SDaniel P. Berrange * size, not AES 128 with truncated digest as might be imagined 2523e308f20SDaniel P. Berrange */ 2533e308f20SDaniel P. Berrange static QCryptoCipherAlgorithm 2543e308f20SDaniel P. Berrange qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm cipher, 2553e308f20SDaniel P. Berrange QCryptoHashAlgorithm hash, 2563e308f20SDaniel P. Berrange Error **errp) 2573e308f20SDaniel P. Berrange { 2583e308f20SDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 2593e308f20SDaniel P. Berrange size_t keylen = qcrypto_cipher_get_key_len(cipher); 2603e308f20SDaniel P. Berrange if (digestlen == keylen) { 2613e308f20SDaniel P. Berrange return cipher; 2623e308f20SDaniel P. Berrange } 2633e308f20SDaniel P. Berrange 2643e308f20SDaniel P. Berrange switch (cipher) { 2653e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_128: 2663e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_192: 2673e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_AES_256: 2683e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 2693e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_128)) { 2703e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_128; 2713e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2723e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_192)) { 2733e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_192; 2743e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2753e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_AES_256)) { 2763e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_AES_256; 2773e308f20SDaniel P. Berrange } else { 2783e308f20SDaniel P. Berrange error_setg(errp, "No AES cipher with key size %zu available", 2793e308f20SDaniel P. Berrange digestlen); 2803e308f20SDaniel P. Berrange return 0; 2813e308f20SDaniel P. Berrange } 2823e308f20SDaniel P. Berrange break; 2833e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_128: 2843e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_192: 2853e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_SERPENT_256: 2863e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 2873e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_128)) { 2883e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_128; 2893e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2903e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_192)) { 2913e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_192; 2923e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 2933e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_SERPENT_256)) { 2943e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_SERPENT_256; 2953e308f20SDaniel P. Berrange } else { 2963e308f20SDaniel P. Berrange error_setg(errp, "No Serpent cipher with key size %zu available", 2973e308f20SDaniel P. Berrange digestlen); 2983e308f20SDaniel P. Berrange return 0; 2993e308f20SDaniel P. Berrange } 3003e308f20SDaniel P. Berrange break; 3013e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_128: 3023e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_192: 3033e308f20SDaniel P. Berrange case QCRYPTO_CIPHER_ALG_TWOFISH_256: 3043e308f20SDaniel P. Berrange if (digestlen == qcrypto_cipher_get_key_len( 3053e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_128)) { 3063e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_128; 3073e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3083e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_192)) { 3093e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_192; 3103e308f20SDaniel P. Berrange } else if (digestlen == qcrypto_cipher_get_key_len( 3113e308f20SDaniel P. Berrange QCRYPTO_CIPHER_ALG_TWOFISH_256)) { 3123e308f20SDaniel P. Berrange return QCRYPTO_CIPHER_ALG_TWOFISH_256; 3133e308f20SDaniel P. Berrange } else { 3143e308f20SDaniel P. Berrange error_setg(errp, "No Twofish cipher with key size %zu available", 3153e308f20SDaniel P. Berrange digestlen); 3163e308f20SDaniel P. Berrange return 0; 3173e308f20SDaniel P. Berrange } 3183e308f20SDaniel P. Berrange break; 3193e308f20SDaniel P. Berrange default: 3203e308f20SDaniel P. Berrange error_setg(errp, "Cipher %s not supported with essiv", 321977c736fSMarkus Armbruster QCryptoCipherAlgorithm_str(cipher)); 3223e308f20SDaniel P. Berrange return 0; 3233e308f20SDaniel P. Berrange } 3243e308f20SDaniel P. Berrange } 3253e308f20SDaniel P. Berrange 3263e308f20SDaniel P. Berrange /* 327bd56a55aSMaxim Levitsky * Returns number of sectors needed to store the key material 328bd56a55aSMaxim Levitsky * given number of anti forensic stripes 329bd56a55aSMaxim Levitsky */ 330bd56a55aSMaxim Levitsky static int 331bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks, 332bd56a55aSMaxim Levitsky unsigned int header_sectors, 333bd56a55aSMaxim Levitsky unsigned int stripes) 334bd56a55aSMaxim Levitsky { 335bd56a55aSMaxim Levitsky /* 336bd56a55aSMaxim Levitsky * This calculation doesn't match that shown in the spec, 337bd56a55aSMaxim Levitsky * but instead follows the cryptsetup implementation. 338bd56a55aSMaxim Levitsky */ 339bd56a55aSMaxim Levitsky 340bd56a55aSMaxim Levitsky size_t splitkeylen = luks->header.master_key_len * stripes; 341bd56a55aSMaxim Levitsky 342bd56a55aSMaxim Levitsky /* First align the key material size to block size*/ 343bd56a55aSMaxim Levitsky size_t splitkeylen_sectors = 344bd56a55aSMaxim Levitsky DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE); 345bd56a55aSMaxim Levitsky 346bd56a55aSMaxim Levitsky /* Then also align the key material size to the size of the header */ 347bd56a55aSMaxim Levitsky return ROUND_UP(splitkeylen_sectors, header_sectors); 348bd56a55aSMaxim Levitsky } 349bd56a55aSMaxim Levitsky 35098c72dfbSDaniel P. Berrangé 35198c72dfbSDaniel P. Berrangé void 35298c72dfbSDaniel P. Berrangé qcrypto_block_luks_to_disk_endian(QCryptoBlockLUKSHeader *hdr) 35398c72dfbSDaniel P. Berrangé { 35498c72dfbSDaniel P. Berrangé size_t i; 35598c72dfbSDaniel P. Berrangé 35698c72dfbSDaniel P. Berrangé /* 35798c72dfbSDaniel P. Berrangé * Everything on disk uses Big Endian (tm), so flip header fields 35898c72dfbSDaniel P. Berrangé * before writing them 35998c72dfbSDaniel P. Berrangé */ 36098c72dfbSDaniel P. Berrangé cpu_to_be16s(&hdr->version); 36198c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->payload_offset_sector); 36298c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->master_key_len); 36398c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->master_key_iterations); 36498c72dfbSDaniel P. Berrangé 36598c72dfbSDaniel P. Berrangé for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 36698c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].active); 36798c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].iterations); 36898c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].key_offset_sector); 36998c72dfbSDaniel P. Berrangé cpu_to_be32s(&hdr->key_slots[i].stripes); 37098c72dfbSDaniel P. Berrangé } 37198c72dfbSDaniel P. Berrangé } 37298c72dfbSDaniel P. Berrangé 37398c72dfbSDaniel P. Berrangé void 37498c72dfbSDaniel P. Berrangé qcrypto_block_luks_from_disk_endian(QCryptoBlockLUKSHeader *hdr) 37598c72dfbSDaniel P. Berrangé { 37698c72dfbSDaniel P. Berrangé size_t i; 37798c72dfbSDaniel P. Berrangé 37898c72dfbSDaniel P. Berrangé /* 37998c72dfbSDaniel P. Berrangé * The header is always stored in big-endian format, so 38098c72dfbSDaniel P. Berrangé * convert everything to native 38198c72dfbSDaniel P. Berrangé */ 38298c72dfbSDaniel P. Berrangé be16_to_cpus(&hdr->version); 38398c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->payload_offset_sector); 38498c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->master_key_len); 38598c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->master_key_iterations); 38698c72dfbSDaniel P. Berrangé 38798c72dfbSDaniel P. Berrangé for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 38898c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].active); 38998c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].iterations); 39098c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].key_offset_sector); 39198c72dfbSDaniel P. Berrangé be32_to_cpus(&hdr->key_slots[i].stripes); 39298c72dfbSDaniel P. Berrangé } 39398c72dfbSDaniel P. Berrangé } 39498c72dfbSDaniel P. Berrangé 395bd56a55aSMaxim Levitsky /* 396dde2c5afSMaxim Levitsky * Stores the main LUKS header, taking care of endianess 397dde2c5afSMaxim Levitsky */ 398dde2c5afSMaxim Levitsky static int 399dde2c5afSMaxim Levitsky qcrypto_block_luks_store_header(QCryptoBlock *block, 400dde2c5afSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 401dde2c5afSMaxim Levitsky void *opaque, 402dde2c5afSMaxim Levitsky Error **errp) 403dde2c5afSMaxim Levitsky { 404dde2c5afSMaxim Levitsky const QCryptoBlockLUKS *luks = block->opaque; 405dde2c5afSMaxim Levitsky Error *local_err = NULL; 406dde2c5afSMaxim Levitsky g_autofree QCryptoBlockLUKSHeader *hdr_copy = NULL; 407dde2c5afSMaxim Levitsky 408dde2c5afSMaxim Levitsky /* Create a copy of the header */ 409dde2c5afSMaxim Levitsky hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1); 410dde2c5afSMaxim Levitsky memcpy(hdr_copy, &luks->header, sizeof(QCryptoBlockLUKSHeader)); 411dde2c5afSMaxim Levitsky 41298c72dfbSDaniel P. Berrangé qcrypto_block_luks_to_disk_endian(hdr_copy); 413dde2c5afSMaxim Levitsky 414dde2c5afSMaxim Levitsky /* Write out the partition header and key slot headers */ 415dde2c5afSMaxim Levitsky writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy), 416dde2c5afSMaxim Levitsky opaque, &local_err); 417dde2c5afSMaxim Levitsky 418dde2c5afSMaxim Levitsky if (local_err) { 419dde2c5afSMaxim Levitsky error_propagate(errp, local_err); 420dde2c5afSMaxim Levitsky return -1; 421dde2c5afSMaxim Levitsky } 422dde2c5afSMaxim Levitsky return 0; 423dde2c5afSMaxim Levitsky } 424dde2c5afSMaxim Levitsky 425dde2c5afSMaxim Levitsky /* 426dde2c5afSMaxim Levitsky * Loads the main LUKS header,and byteswaps it to native endianess 427dde2c5afSMaxim Levitsky * And run basic sanity checks on it 428dde2c5afSMaxim Levitsky */ 429dde2c5afSMaxim Levitsky static int 430dde2c5afSMaxim Levitsky qcrypto_block_luks_load_header(QCryptoBlock *block, 431dde2c5afSMaxim Levitsky QCryptoBlockReadFunc readfunc, 432dde2c5afSMaxim Levitsky void *opaque, 433dde2c5afSMaxim Levitsky Error **errp) 434dde2c5afSMaxim Levitsky { 435757dda54SAlberto Faria int rv; 436dde2c5afSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 437dde2c5afSMaxim Levitsky 438dde2c5afSMaxim Levitsky /* 439dde2c5afSMaxim Levitsky * Read the entire LUKS header, minus the key material from 440dde2c5afSMaxim Levitsky * the underlying device 441dde2c5afSMaxim Levitsky */ 442dde2c5afSMaxim Levitsky rv = readfunc(block, 0, 443dde2c5afSMaxim Levitsky (uint8_t *)&luks->header, 444dde2c5afSMaxim Levitsky sizeof(luks->header), 445dde2c5afSMaxim Levitsky opaque, 446dde2c5afSMaxim Levitsky errp); 447dde2c5afSMaxim Levitsky if (rv < 0) { 448dde2c5afSMaxim Levitsky return rv; 449dde2c5afSMaxim Levitsky } 450dde2c5afSMaxim Levitsky 45198c72dfbSDaniel P. Berrangé qcrypto_block_luks_from_disk_endian(&luks->header); 452dde2c5afSMaxim Levitsky 453dde2c5afSMaxim Levitsky return 0; 454dde2c5afSMaxim Levitsky } 455dde2c5afSMaxim Levitsky 456dde2c5afSMaxim Levitsky /* 4579fa9c1c2SMaxim Levitsky * Does basic sanity checks on the LUKS header 4589fa9c1c2SMaxim Levitsky */ 4599fa9c1c2SMaxim Levitsky static int 4609fa9c1c2SMaxim Levitsky qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp) 4619fa9c1c2SMaxim Levitsky { 462befdba9eSMaxim Levitsky size_t i, j; 463befdba9eSMaxim Levitsky 464befdba9eSMaxim Levitsky unsigned int header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 465befdba9eSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 466befdba9eSMaxim Levitsky 4679fa9c1c2SMaxim Levitsky if (memcmp(luks->header.magic, qcrypto_block_luks_magic, 4689fa9c1c2SMaxim Levitsky QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) { 4699fa9c1c2SMaxim Levitsky error_setg(errp, "Volume is not in LUKS format"); 4709fa9c1c2SMaxim Levitsky return -1; 4719fa9c1c2SMaxim Levitsky } 4729fa9c1c2SMaxim Levitsky 4739fa9c1c2SMaxim Levitsky if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) { 4749fa9c1c2SMaxim Levitsky error_setg(errp, "LUKS version %" PRIu32 " is not supported", 4759fa9c1c2SMaxim Levitsky luks->header.version); 4769fa9c1c2SMaxim Levitsky return -1; 4779fa9c1c2SMaxim Levitsky } 478befdba9eSMaxim Levitsky 479c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_name, '\0', 480c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_name))) { 481c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher name is not NUL terminated"); 482c1d8634cSDaniel P. Berrangé return -1; 483c1d8634cSDaniel P. Berrangé } 484c1d8634cSDaniel P. Berrangé 485c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.cipher_mode, '\0', 486c1d8634cSDaniel P. Berrangé sizeof(luks->header.cipher_mode))) { 487c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header cipher mode is not NUL terminated"); 488c1d8634cSDaniel P. Berrangé return -1; 489c1d8634cSDaniel P. Berrangé } 490c1d8634cSDaniel P. Berrangé 491c1d8634cSDaniel P. Berrangé if (!memchr(luks->header.hash_spec, '\0', 492c1d8634cSDaniel P. Berrangé sizeof(luks->header.hash_spec))) { 493c1d8634cSDaniel P. Berrangé error_setg(errp, "LUKS header hash spec is not NUL terminated"); 494c1d8634cSDaniel P. Berrangé return -1; 495c1d8634cSDaniel P. Berrangé } 496c1d8634cSDaniel P. Berrangé 497d233fbc3SDaniel P. Berrangé if (luks->header.payload_offset_sector < 498d233fbc3SDaniel P. Berrangé DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 499d233fbc3SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 500d233fbc3SDaniel P. Berrangé error_setg(errp, "LUKS payload is overlapping with the header"); 501d233fbc3SDaniel P. Berrangé return -1; 502d233fbc3SDaniel P. Berrangé } 503d233fbc3SDaniel P. Berrangé 504b57151acSDaniel P. Berrangé if (luks->header.master_key_iterations == 0) { 505b57151acSDaniel P. Berrangé error_setg(errp, "LUKS key iteration count is zero"); 506b57151acSDaniel P. Berrangé return -1; 507b57151acSDaniel P. Berrangé } 508b57151acSDaniel P. Berrangé 509befdba9eSMaxim Levitsky /* Check all keyslots for corruption */ 510befdba9eSMaxim Levitsky for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) { 511befdba9eSMaxim Levitsky 512befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot1 = &luks->header.key_slots[i]; 513befdba9eSMaxim Levitsky unsigned int start1 = slot1->key_offset_sector; 514befdba9eSMaxim Levitsky unsigned int len1 = 515befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 516befdba9eSMaxim Levitsky header_sectors, 517befdba9eSMaxim Levitsky slot1->stripes); 518befdba9eSMaxim Levitsky 519f1195961SDaniel P. Berrangé if (slot1->stripes != QCRYPTO_BLOCK_LUKS_STRIPES) { 520f1195961SDaniel P. Berrangé error_setg(errp, "Keyslot %zu is corrupted (stripes %d != %d)", 521f1195961SDaniel P. Berrangé i, slot1->stripes, QCRYPTO_BLOCK_LUKS_STRIPES); 522befdba9eSMaxim Levitsky return -1; 523befdba9eSMaxim Levitsky } 524befdba9eSMaxim Levitsky 525befdba9eSMaxim Levitsky if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED && 526befdba9eSMaxim Levitsky slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 527befdba9eSMaxim Levitsky error_setg(errp, 528befdba9eSMaxim Levitsky "Keyslot %zu state (active/disable) is corrupted", i); 529befdba9eSMaxim Levitsky return -1; 530befdba9eSMaxim Levitsky } 531befdba9eSMaxim Levitsky 532b57151acSDaniel P. Berrangé if (slot1->active == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED && 533b57151acSDaniel P. Berrangé slot1->iterations == 0) { 534b57151acSDaniel P. Berrangé error_setg(errp, "Keyslot %zu iteration count is zero", i); 535b57151acSDaniel P. Berrangé return -1; 536b57151acSDaniel P. Berrangé } 537b57151acSDaniel P. Berrangé 538c5f69628SDaniel P. Berrangé if (start1 < DIV_ROUND_UP(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET, 53993569c37SDaniel P. Berrangé QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) { 54093569c37SDaniel P. Berrangé error_setg(errp, 54193569c37SDaniel P. Berrangé "Keyslot %zu is overlapping with the LUKS header", 54293569c37SDaniel P. Berrangé i); 54393569c37SDaniel P. Berrangé return -1; 54493569c37SDaniel P. Berrangé } 54593569c37SDaniel P. Berrangé 546befdba9eSMaxim Levitsky if (start1 + len1 > luks->header.payload_offset_sector) { 547befdba9eSMaxim Levitsky error_setg(errp, 548befdba9eSMaxim Levitsky "Keyslot %zu is overlapping with the encrypted payload", 549befdba9eSMaxim Levitsky i); 550befdba9eSMaxim Levitsky return -1; 551befdba9eSMaxim Levitsky } 552befdba9eSMaxim Levitsky 553befdba9eSMaxim Levitsky for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) { 554befdba9eSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot2 = &luks->header.key_slots[j]; 555befdba9eSMaxim Levitsky unsigned int start2 = slot2->key_offset_sector; 556befdba9eSMaxim Levitsky unsigned int len2 = 557befdba9eSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 558befdba9eSMaxim Levitsky header_sectors, 559befdba9eSMaxim Levitsky slot2->stripes); 560befdba9eSMaxim Levitsky 561befdba9eSMaxim Levitsky if (start1 + len1 > start2 && start2 + len2 > start1) { 562befdba9eSMaxim Levitsky error_setg(errp, 563befdba9eSMaxim Levitsky "Keyslots %zu and %zu are overlapping in the header", 564befdba9eSMaxim Levitsky i, j); 565befdba9eSMaxim Levitsky return -1; 566befdba9eSMaxim Levitsky } 567befdba9eSMaxim Levitsky } 568befdba9eSMaxim Levitsky 569befdba9eSMaxim Levitsky } 5709fa9c1c2SMaxim Levitsky return 0; 5719fa9c1c2SMaxim Levitsky } 5729fa9c1c2SMaxim Levitsky 5739fa9c1c2SMaxim Levitsky /* 5749fa9c1c2SMaxim Levitsky * Parses the crypto parameters that are stored in the LUKS header 5759fa9c1c2SMaxim Levitsky */ 5769fa9c1c2SMaxim Levitsky 5779fa9c1c2SMaxim Levitsky static int 5789fa9c1c2SMaxim Levitsky qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp) 5799fa9c1c2SMaxim Levitsky { 5809fa9c1c2SMaxim Levitsky g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode); 5819fa9c1c2SMaxim Levitsky char *ivgen_name, *ivhash_name; 5829fa9c1c2SMaxim Levitsky Error *local_err = NULL; 5839fa9c1c2SMaxim Levitsky 5849fa9c1c2SMaxim Levitsky /* 5859fa9c1c2SMaxim Levitsky * The cipher_mode header contains a string that we have 5869fa9c1c2SMaxim Levitsky * to further parse, of the format 5879fa9c1c2SMaxim Levitsky * 5889fa9c1c2SMaxim Levitsky * <cipher-mode>-<iv-generator>[:<iv-hash>] 5899fa9c1c2SMaxim Levitsky * 5909fa9c1c2SMaxim Levitsky * eg cbc-essiv:sha256, cbc-plain64 5919fa9c1c2SMaxim Levitsky */ 5929fa9c1c2SMaxim Levitsky ivgen_name = strchr(cipher_mode, '-'); 5939fa9c1c2SMaxim Levitsky if (!ivgen_name) { 5946c198932SDaniel P. Berrangé error_setg(errp, "Unexpected cipher mode string format '%s'", 5959fa9c1c2SMaxim Levitsky luks->header.cipher_mode); 5969fa9c1c2SMaxim Levitsky return -1; 5979fa9c1c2SMaxim Levitsky } 5989fa9c1c2SMaxim Levitsky *ivgen_name = '\0'; 5999fa9c1c2SMaxim Levitsky ivgen_name++; 6009fa9c1c2SMaxim Levitsky 6019fa9c1c2SMaxim Levitsky ivhash_name = strchr(ivgen_name, ':'); 6029fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6039fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = 0; 6049fa9c1c2SMaxim Levitsky } else { 6059fa9c1c2SMaxim Levitsky *ivhash_name = '\0'; 6069fa9c1c2SMaxim Levitsky ivhash_name++; 6079fa9c1c2SMaxim Levitsky 6089fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg = qcrypto_block_luks_hash_name_lookup(ivhash_name, 6099fa9c1c2SMaxim Levitsky &local_err); 6109fa9c1c2SMaxim Levitsky if (local_err) { 6119fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6129fa9c1c2SMaxim Levitsky return -1; 6139fa9c1c2SMaxim Levitsky } 6149fa9c1c2SMaxim Levitsky } 6159fa9c1c2SMaxim Levitsky 6169fa9c1c2SMaxim Levitsky luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode, 6179fa9c1c2SMaxim Levitsky &local_err); 6189fa9c1c2SMaxim Levitsky if (local_err) { 6199fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6209fa9c1c2SMaxim Levitsky return -1; 6219fa9c1c2SMaxim Levitsky } 6229fa9c1c2SMaxim Levitsky 6239fa9c1c2SMaxim Levitsky luks->cipher_alg = 6249fa9c1c2SMaxim Levitsky qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name, 6259fa9c1c2SMaxim Levitsky luks->cipher_mode, 6269fa9c1c2SMaxim Levitsky luks->header.master_key_len, 6279fa9c1c2SMaxim Levitsky &local_err); 6289fa9c1c2SMaxim Levitsky if (local_err) { 6299fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6309fa9c1c2SMaxim Levitsky return -1; 6319fa9c1c2SMaxim Levitsky } 6329fa9c1c2SMaxim Levitsky 6339fa9c1c2SMaxim Levitsky luks->hash_alg = 6349fa9c1c2SMaxim Levitsky qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec, 6359fa9c1c2SMaxim Levitsky &local_err); 6369fa9c1c2SMaxim Levitsky if (local_err) { 6379fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6389fa9c1c2SMaxim Levitsky return -1; 6399fa9c1c2SMaxim Levitsky } 6409fa9c1c2SMaxim Levitsky 6419fa9c1c2SMaxim Levitsky luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name, 6429fa9c1c2SMaxim Levitsky &local_err); 6439fa9c1c2SMaxim Levitsky if (local_err) { 6449fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6459fa9c1c2SMaxim Levitsky return -1; 6469fa9c1c2SMaxim Levitsky } 6479fa9c1c2SMaxim Levitsky 6489fa9c1c2SMaxim Levitsky if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 6499fa9c1c2SMaxim Levitsky if (!ivhash_name) { 6509fa9c1c2SMaxim Levitsky error_setg(errp, "Missing IV generator hash specification"); 6519fa9c1c2SMaxim Levitsky return -1; 6529fa9c1c2SMaxim Levitsky } 6539fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = 6549fa9c1c2SMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks->cipher_alg, 6559fa9c1c2SMaxim Levitsky luks->ivgen_hash_alg, 6569fa9c1c2SMaxim Levitsky &local_err); 6579fa9c1c2SMaxim Levitsky if (local_err) { 6589fa9c1c2SMaxim Levitsky error_propagate(errp, local_err); 6599fa9c1c2SMaxim Levitsky return -1; 6609fa9c1c2SMaxim Levitsky } 6619fa9c1c2SMaxim Levitsky } else { 6629fa9c1c2SMaxim Levitsky 6639fa9c1c2SMaxim Levitsky /* 6649fa9c1c2SMaxim Levitsky * Note we parsed the ivhash_name earlier in the cipher_mode 6659fa9c1c2SMaxim Levitsky * spec string even with plain/plain64 ivgens, but we 6669fa9c1c2SMaxim Levitsky * will ignore it, since it is irrelevant for these ivgens. 6679fa9c1c2SMaxim Levitsky * This is for compat with dm-crypt which will silently 6689fa9c1c2SMaxim Levitsky * ignore hash names with these ivgens rather than report 6699fa9c1c2SMaxim Levitsky * an error about the invalid usage 6709fa9c1c2SMaxim Levitsky */ 6719fa9c1c2SMaxim Levitsky luks->ivgen_cipher_alg = luks->cipher_alg; 6729fa9c1c2SMaxim Levitsky } 6739fa9c1c2SMaxim Levitsky return 0; 6749fa9c1c2SMaxim Levitsky } 6759fa9c1c2SMaxim Levitsky 6769fa9c1c2SMaxim Levitsky /* 6773994a7c9SMaxim Levitsky * Given a key slot, user password, and the master key, 6783994a7c9SMaxim Levitsky * will store the encrypted master key there, and update the 6793994a7c9SMaxim Levitsky * in-memory header. User must then write the in-memory header 6803994a7c9SMaxim Levitsky * 6813994a7c9SMaxim Levitsky * Returns: 6823994a7c9SMaxim Levitsky * 0 if the keyslot was written successfully 6833994a7c9SMaxim Levitsky * with the provided password 6843994a7c9SMaxim Levitsky * -1 if a fatal error occurred while storing the key 6853994a7c9SMaxim Levitsky */ 6863994a7c9SMaxim Levitsky static int 6873994a7c9SMaxim Levitsky qcrypto_block_luks_store_key(QCryptoBlock *block, 6883994a7c9SMaxim Levitsky unsigned int slot_idx, 6893994a7c9SMaxim Levitsky const char *password, 6903994a7c9SMaxim Levitsky uint8_t *masterkey, 6913994a7c9SMaxim Levitsky uint64_t iter_time, 6923994a7c9SMaxim Levitsky QCryptoBlockWriteFunc writefunc, 6933994a7c9SMaxim Levitsky void *opaque, 6943994a7c9SMaxim Levitsky Error **errp) 6953994a7c9SMaxim Levitsky { 6963994a7c9SMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 697557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 6983994a7c9SMaxim Levitsky g_autofree uint8_t *splitkey = NULL; 6993994a7c9SMaxim Levitsky size_t splitkeylen; 7003994a7c9SMaxim Levitsky g_autofree uint8_t *slotkey = NULL; 7013994a7c9SMaxim Levitsky g_autoptr(QCryptoCipher) cipher = NULL; 7023994a7c9SMaxim Levitsky g_autoptr(QCryptoIVGen) ivgen = NULL; 7033994a7c9SMaxim Levitsky Error *local_err = NULL; 7043994a7c9SMaxim Levitsky uint64_t iters; 7053994a7c9SMaxim Levitsky int ret = -1; 7063994a7c9SMaxim Levitsky 707557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 708557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 70955a01cabSAkihiko Odaki splitkeylen = luks->header.master_key_len * slot->stripes; 71055a01cabSAkihiko Odaki 7113994a7c9SMaxim Levitsky if (qcrypto_random_bytes(slot->salt, 7123994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7133994a7c9SMaxim Levitsky errp) < 0) { 7143994a7c9SMaxim Levitsky goto cleanup; 7153994a7c9SMaxim Levitsky } 7163994a7c9SMaxim Levitsky 7173994a7c9SMaxim Levitsky /* 7183994a7c9SMaxim Levitsky * Determine how many iterations are required to 7193994a7c9SMaxim Levitsky * hash the user password while consuming 1 second of compute 7203994a7c9SMaxim Levitsky * time 7213994a7c9SMaxim Levitsky */ 7223994a7c9SMaxim Levitsky iters = qcrypto_pbkdf2_count_iters(luks->hash_alg, 7233994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7243994a7c9SMaxim Levitsky slot->salt, 7253994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7263994a7c9SMaxim Levitsky luks->header.master_key_len, 7273994a7c9SMaxim Levitsky &local_err); 7283994a7c9SMaxim Levitsky if (local_err) { 7293994a7c9SMaxim Levitsky error_propagate(errp, local_err); 7303994a7c9SMaxim Levitsky goto cleanup; 7313994a7c9SMaxim Levitsky } 7323994a7c9SMaxim Levitsky 7333994a7c9SMaxim Levitsky if (iters > (ULLONG_MAX / iter_time)) { 7343994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7353994a7c9SMaxim Levitsky "PBKDF iterations %llu too large to scale", 7363994a7c9SMaxim Levitsky (unsigned long long)iters); 7373994a7c9SMaxim Levitsky goto cleanup; 7383994a7c9SMaxim Levitsky } 7393994a7c9SMaxim Levitsky 7403994a7c9SMaxim Levitsky /* iter_time was in millis, but count_iters reported for secs */ 7413994a7c9SMaxim Levitsky iters = iters * iter_time / 1000; 7423994a7c9SMaxim Levitsky 7433994a7c9SMaxim Levitsky if (iters > UINT32_MAX) { 7443994a7c9SMaxim Levitsky error_setg_errno(errp, ERANGE, 7453994a7c9SMaxim Levitsky "PBKDF iterations %llu larger than %u", 7463994a7c9SMaxim Levitsky (unsigned long long)iters, UINT32_MAX); 7473994a7c9SMaxim Levitsky goto cleanup; 7483994a7c9SMaxim Levitsky } 7493994a7c9SMaxim Levitsky 7503994a7c9SMaxim Levitsky slot->iterations = 7513994a7c9SMaxim Levitsky MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS); 7523994a7c9SMaxim Levitsky 7533994a7c9SMaxim Levitsky 7543994a7c9SMaxim Levitsky /* 7553994a7c9SMaxim Levitsky * Generate a key that we'll use to encrypt the master 7563994a7c9SMaxim Levitsky * key, from the user's password 7573994a7c9SMaxim Levitsky */ 7583994a7c9SMaxim Levitsky slotkey = g_new0(uint8_t, luks->header.master_key_len); 7593994a7c9SMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 7603994a7c9SMaxim Levitsky (uint8_t *)password, strlen(password), 7613994a7c9SMaxim Levitsky slot->salt, 7623994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SALT_LEN, 7633994a7c9SMaxim Levitsky slot->iterations, 7643994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7653994a7c9SMaxim Levitsky errp) < 0) { 7663994a7c9SMaxim Levitsky goto cleanup; 7673994a7c9SMaxim Levitsky } 7683994a7c9SMaxim Levitsky 7693994a7c9SMaxim Levitsky 7703994a7c9SMaxim Levitsky /* 7713994a7c9SMaxim Levitsky * Setup the encryption objects needed to encrypt the 7723994a7c9SMaxim Levitsky * master key material 7733994a7c9SMaxim Levitsky */ 7743994a7c9SMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 7753994a7c9SMaxim Levitsky luks->cipher_mode, 7763994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7773994a7c9SMaxim Levitsky errp); 7783994a7c9SMaxim Levitsky if (!cipher) { 7793994a7c9SMaxim Levitsky goto cleanup; 7803994a7c9SMaxim Levitsky } 7813994a7c9SMaxim Levitsky 7823994a7c9SMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 7833994a7c9SMaxim Levitsky luks->ivgen_cipher_alg, 7843994a7c9SMaxim Levitsky luks->ivgen_hash_alg, 7853994a7c9SMaxim Levitsky slotkey, luks->header.master_key_len, 7863994a7c9SMaxim Levitsky errp); 7873994a7c9SMaxim Levitsky if (!ivgen) { 7883994a7c9SMaxim Levitsky goto cleanup; 7893994a7c9SMaxim Levitsky } 7903994a7c9SMaxim Levitsky 7913994a7c9SMaxim Levitsky /* 7923994a7c9SMaxim Levitsky * Before storing the master key, we need to vastly 7933994a7c9SMaxim Levitsky * increase its size, as protection against forensic 7943994a7c9SMaxim Levitsky * disk data recovery 7953994a7c9SMaxim Levitsky */ 7963994a7c9SMaxim Levitsky splitkey = g_new0(uint8_t, splitkeylen); 7973994a7c9SMaxim Levitsky 7983994a7c9SMaxim Levitsky if (qcrypto_afsplit_encode(luks->hash_alg, 7993994a7c9SMaxim Levitsky luks->header.master_key_len, 8003994a7c9SMaxim Levitsky slot->stripes, 8013994a7c9SMaxim Levitsky masterkey, 8023994a7c9SMaxim Levitsky splitkey, 8033994a7c9SMaxim Levitsky errp) < 0) { 8043994a7c9SMaxim Levitsky goto cleanup; 8053994a7c9SMaxim Levitsky } 8063994a7c9SMaxim Levitsky 8073994a7c9SMaxim Levitsky /* 8083994a7c9SMaxim Levitsky * Now we encrypt the split master key with the key generated 8093994a7c9SMaxim Levitsky * from the user's password, before storing it 8103994a7c9SMaxim Levitsky */ 8113994a7c9SMaxim Levitsky if (qcrypto_block_cipher_encrypt_helper(cipher, block->niv, ivgen, 8123994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8133994a7c9SMaxim Levitsky 0, 8143994a7c9SMaxim Levitsky splitkey, 8153994a7c9SMaxim Levitsky splitkeylen, 8163994a7c9SMaxim Levitsky errp) < 0) { 8173994a7c9SMaxim Levitsky goto cleanup; 8183994a7c9SMaxim Levitsky } 8193994a7c9SMaxim Levitsky 8203994a7c9SMaxim Levitsky /* Write out the slot's master key material. */ 8213994a7c9SMaxim Levitsky if (writefunc(block, 8223994a7c9SMaxim Levitsky slot->key_offset_sector * 8233994a7c9SMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 8243994a7c9SMaxim Levitsky splitkey, splitkeylen, 8253994a7c9SMaxim Levitsky opaque, 826757dda54SAlberto Faria errp) < 0) { 8273994a7c9SMaxim Levitsky goto cleanup; 8283994a7c9SMaxim Levitsky } 8293994a7c9SMaxim Levitsky 8303994a7c9SMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 8313994a7c9SMaxim Levitsky 8323994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_header(block, writefunc, opaque, errp) < 0) { 8333994a7c9SMaxim Levitsky goto cleanup; 8343994a7c9SMaxim Levitsky } 8353994a7c9SMaxim Levitsky 8363994a7c9SMaxim Levitsky ret = 0; 8373994a7c9SMaxim Levitsky 8383994a7c9SMaxim Levitsky cleanup: 8393994a7c9SMaxim Levitsky if (slotkey) { 8403994a7c9SMaxim Levitsky memset(slotkey, 0, luks->header.master_key_len); 8413994a7c9SMaxim Levitsky } 8423994a7c9SMaxim Levitsky if (splitkey) { 8433994a7c9SMaxim Levitsky memset(splitkey, 0, splitkeylen); 8443994a7c9SMaxim Levitsky } 8453994a7c9SMaxim Levitsky return ret; 8463994a7c9SMaxim Levitsky } 8473994a7c9SMaxim Levitsky 8483994a7c9SMaxim Levitsky /* 8493e308f20SDaniel P. Berrange * Given a key slot, and user password, this will attempt to unlock 8503e308f20SDaniel P. Berrange * the master encryption key from the key slot. 8513e308f20SDaniel P. Berrange * 8523e308f20SDaniel P. Berrange * Returns: 8533e308f20SDaniel P. Berrange * 0 if the key slot is disabled, or key could not be decrypted 8543e308f20SDaniel P. Berrange * with the provided password 8553e308f20SDaniel P. Berrange * 1 if the key slot is enabled, and key decrypted successfully 8563e308f20SDaniel P. Berrange * with the provided password 8573e308f20SDaniel P. Berrange * -1 if a fatal error occurred loading the key 8583e308f20SDaniel P. Berrange */ 8593e308f20SDaniel P. Berrange static int 8603e308f20SDaniel P. Berrange qcrypto_block_luks_load_key(QCryptoBlock *block, 8617e60a6f5SMaxim Levitsky size_t slot_idx, 8623e308f20SDaniel P. Berrange const char *password, 8633e308f20SDaniel P. Berrange uint8_t *masterkey, 8643e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 8653e308f20SDaniel P. Berrange void *opaque, 8663e308f20SDaniel P. Berrange Error **errp) 8673e308f20SDaniel P. Berrange { 8683e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 869557d2bdcSMaxim Levitsky const QCryptoBlockLUKSKeySlot *slot; 87057b9f113SDaniel P. Berrangé g_autofree uint8_t *splitkey = NULL; 8713e308f20SDaniel P. Berrange size_t splitkeylen; 87257b9f113SDaniel P. Berrangé g_autofree uint8_t *possiblekey = NULL; 873757dda54SAlberto Faria int rv; 87457b9f113SDaniel P. Berrangé g_autoptr(QCryptoCipher) cipher = NULL; 8753e308f20SDaniel P. Berrange uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN]; 87657b9f113SDaniel P. Berrangé g_autoptr(QCryptoIVGen) ivgen = NULL; 8773e308f20SDaniel P. Berrange size_t niv; 8783e308f20SDaniel P. Berrange 879557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 880557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 8813e308f20SDaniel P. Berrange if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 8823e308f20SDaniel P. Berrange return 0; 8833e308f20SDaniel P. Berrange } 8843e308f20SDaniel P. Berrange 8851ddd52e4SMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 8863e308f20SDaniel P. Berrange splitkey = g_new0(uint8_t, splitkeylen); 8871ddd52e4SMaxim Levitsky possiblekey = g_new0(uint8_t, luks->header.master_key_len); 8883e308f20SDaniel P. Berrange 8893e308f20SDaniel P. Berrange /* 8903e308f20SDaniel P. Berrange * The user password is used to generate a (possible) 8913e308f20SDaniel P. Berrange * decryption key. This may or may not successfully 8923e308f20SDaniel P. Berrange * decrypt the master key - we just blindly assume 8933e308f20SDaniel P. Berrange * the key is correct and validate the results of 8943e308f20SDaniel P. Berrange * decryption later. 8953e308f20SDaniel P. Berrange */ 8969d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 8973e308f20SDaniel P. Berrange (const uint8_t *)password, strlen(password), 8983e308f20SDaniel P. Berrange slot->salt, QCRYPTO_BLOCK_LUKS_SALT_LEN, 8993e308f20SDaniel P. Berrange slot->iterations, 9001ddd52e4SMaxim Levitsky possiblekey, luks->header.master_key_len, 9013e308f20SDaniel P. Berrange errp) < 0) { 90257b9f113SDaniel P. Berrangé return -1; 9033e308f20SDaniel P. Berrange } 9043e308f20SDaniel P. Berrange 9053e308f20SDaniel P. Berrange /* 9063e308f20SDaniel P. Berrange * We need to read the master key material from the 9073e308f20SDaniel P. Berrange * LUKS key material header. What we're reading is 9083e308f20SDaniel P. Berrange * not the raw master key, but rather the data after 9093e308f20SDaniel P. Berrange * it has been passed through AFSplit and the result 9103e308f20SDaniel P. Berrange * then encrypted. 9113e308f20SDaniel P. Berrange */ 9123e308f20SDaniel P. Berrange rv = readfunc(block, 913f0d3c362SMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9143e308f20SDaniel P. Berrange splitkey, splitkeylen, 915e4a3507eSDaniel P. Berrange opaque, 91637509233SFam Zheng errp); 9173e308f20SDaniel P. Berrange if (rv < 0) { 91857b9f113SDaniel P. Berrangé return -1; 9193e308f20SDaniel P. Berrange } 9203e308f20SDaniel P. Berrange 9213e308f20SDaniel P. Berrange 9223e308f20SDaniel P. Berrange /* Setup the cipher/ivgen that we'll use to try to decrypt 9233e308f20SDaniel P. Berrange * the split master key material */ 9249d80e59dSMaxim Levitsky cipher = qcrypto_cipher_new(luks->cipher_alg, 9259d80e59dSMaxim Levitsky luks->cipher_mode, 9269d80e59dSMaxim Levitsky possiblekey, 9279d80e59dSMaxim Levitsky luks->header.master_key_len, 9283e308f20SDaniel P. Berrange errp); 9293e308f20SDaniel P. Berrange if (!cipher) { 93057b9f113SDaniel P. Berrangé return -1; 9313e308f20SDaniel P. Berrange } 9323e308f20SDaniel P. Berrange 9339d80e59dSMaxim Levitsky niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 9349d80e59dSMaxim Levitsky luks->cipher_mode); 9359d80e59dSMaxim Levitsky 9369d80e59dSMaxim Levitsky ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 9379d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 9389d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 9399d80e59dSMaxim Levitsky possiblekey, 9409d80e59dSMaxim Levitsky luks->header.master_key_len, 9413e308f20SDaniel P. Berrange errp); 9423e308f20SDaniel P. Berrange if (!ivgen) { 94357b9f113SDaniel P. Berrangé return -1; 9443e308f20SDaniel P. Berrange } 9453e308f20SDaniel P. Berrange 9463e308f20SDaniel P. Berrange 9473e308f20SDaniel P. Berrange /* 9483e308f20SDaniel P. Berrange * The master key needs to be decrypted in the same 9493e308f20SDaniel P. Berrange * way that the block device payload will be decrypted 9503e308f20SDaniel P. Berrange * later. In particular we'll be using the IV generator 9513e308f20SDaniel P. Berrange * to reset the encryption cipher every time the master 9523e308f20SDaniel P. Berrange * key crosses a sector boundary. 9533e308f20SDaniel P. Berrange */ 9540270417cSVladimir Sementsov-Ogievskiy if (qcrypto_block_cipher_decrypt_helper(cipher, 9553e308f20SDaniel P. Berrange niv, 9563e308f20SDaniel P. Berrange ivgen, 9573e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 9583e308f20SDaniel P. Berrange 0, 9593e308f20SDaniel P. Berrange splitkey, 9603e308f20SDaniel P. Berrange splitkeylen, 9613e308f20SDaniel P. Berrange errp) < 0) { 96257b9f113SDaniel P. Berrangé return -1; 9633e308f20SDaniel P. Berrange } 9643e308f20SDaniel P. Berrange 9653e308f20SDaniel P. Berrange /* 9663e308f20SDaniel P. Berrange * Now we've decrypted the split master key, join 9673e308f20SDaniel P. Berrange * it back together to get the actual master key. 9683e308f20SDaniel P. Berrange */ 9699d80e59dSMaxim Levitsky if (qcrypto_afsplit_decode(luks->hash_alg, 9701ddd52e4SMaxim Levitsky luks->header.master_key_len, 9713e308f20SDaniel P. Berrange slot->stripes, 9723e308f20SDaniel P. Berrange splitkey, 9733e308f20SDaniel P. Berrange masterkey, 9743e308f20SDaniel P. Berrange errp) < 0) { 97557b9f113SDaniel P. Berrangé return -1; 9763e308f20SDaniel P. Berrange } 9773e308f20SDaniel P. Berrange 9783e308f20SDaniel P. Berrange 9793e308f20SDaniel P. Berrange /* 9803e308f20SDaniel P. Berrange * We still don't know that the masterkey we got is valid, 9813e308f20SDaniel P. Berrange * because we just blindly assumed the user's password 9823e308f20SDaniel P. Berrange * was correct. This is where we now verify it. We are 9833e308f20SDaniel P. Berrange * creating a hash of the master key using PBKDF and 9843e308f20SDaniel P. Berrange * then comparing that to the hash stored in the key slot 9853e308f20SDaniel P. Berrange * header 9863e308f20SDaniel P. Berrange */ 9879d80e59dSMaxim Levitsky if (qcrypto_pbkdf2(luks->hash_alg, 9881ddd52e4SMaxim Levitsky masterkey, 9891ddd52e4SMaxim Levitsky luks->header.master_key_len, 9903e308f20SDaniel P. Berrange luks->header.master_key_salt, 9913e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 9923e308f20SDaniel P. Berrange luks->header.master_key_iterations, 9931ddd52e4SMaxim Levitsky keydigest, 9941ddd52e4SMaxim Levitsky G_N_ELEMENTS(keydigest), 9953e308f20SDaniel P. Berrange errp) < 0) { 99657b9f113SDaniel P. Berrangé return -1; 9973e308f20SDaniel P. Berrange } 9983e308f20SDaniel P. Berrange 9993e308f20SDaniel P. Berrange if (memcmp(keydigest, luks->header.master_key_digest, 10003e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) { 10013e308f20SDaniel P. Berrange /* Success, we got the right master key */ 100257b9f113SDaniel P. Berrangé return 1; 10033e308f20SDaniel P. Berrange } 10043e308f20SDaniel P. Berrange 10053e308f20SDaniel P. Berrange /* Fail, user's password was not valid for this key slot, 10063e308f20SDaniel P. Berrange * tell caller to try another slot */ 100757b9f113SDaniel P. Berrangé return 0; 10083e308f20SDaniel P. Berrange } 10093e308f20SDaniel P. Berrange 10103e308f20SDaniel P. Berrange 10113e308f20SDaniel P. Berrange /* 10123e308f20SDaniel P. Berrange * Given a user password, this will iterate over all key 10133e308f20SDaniel P. Berrange * slots and try to unlock each active key slot using the 10143e308f20SDaniel P. Berrange * password until it successfully obtains a master key. 10153e308f20SDaniel P. Berrange * 10163e308f20SDaniel P. Berrange * Returns 0 if a key was loaded, -1 if no keys could be loaded 10173e308f20SDaniel P. Berrange */ 10183e308f20SDaniel P. Berrange static int 10193e308f20SDaniel P. Berrange qcrypto_block_luks_find_key(QCryptoBlock *block, 10203e308f20SDaniel P. Berrange const char *password, 10211ddd52e4SMaxim Levitsky uint8_t *masterkey, 10223e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 10233e308f20SDaniel P. Berrange void *opaque, 10243e308f20SDaniel P. Berrange Error **errp) 10253e308f20SDaniel P. Berrange { 10263e308f20SDaniel P. Berrange size_t i; 10273e308f20SDaniel P. Berrange int rv; 10283e308f20SDaniel P. Berrange 10293e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 10303e308f20SDaniel P. Berrange rv = qcrypto_block_luks_load_key(block, 10317e60a6f5SMaxim Levitsky i, 10323e308f20SDaniel P. Berrange password, 10331ddd52e4SMaxim Levitsky masterkey, 10343e308f20SDaniel P. Berrange readfunc, 10353e308f20SDaniel P. Berrange opaque, 10363e308f20SDaniel P. Berrange errp); 10373e308f20SDaniel P. Berrange if (rv < 0) { 10383e308f20SDaniel P. Berrange goto error; 10393e308f20SDaniel P. Berrange } 10403e308f20SDaniel P. Berrange if (rv == 1) { 10413e308f20SDaniel P. Berrange return 0; 10423e308f20SDaniel P. Berrange } 10433e308f20SDaniel P. Berrange } 10443e308f20SDaniel P. Berrange 10453e308f20SDaniel P. Berrange error_setg(errp, "Invalid password, cannot unlock any keyslot"); 10463e308f20SDaniel P. Berrange error: 10473e308f20SDaniel P. Berrange return -1; 10483e308f20SDaniel P. Berrange } 10493e308f20SDaniel P. Berrange 1050557d2bdcSMaxim Levitsky /* 1051557d2bdcSMaxim Levitsky * Returns true if a slot i is marked as active 1052557d2bdcSMaxim Levitsky * (contains encrypted copy of the master key) 1053557d2bdcSMaxim Levitsky */ 1054557d2bdcSMaxim Levitsky static bool 1055557d2bdcSMaxim Levitsky qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, 1056557d2bdcSMaxim Levitsky unsigned int slot_idx) 1057557d2bdcSMaxim Levitsky { 1058557d2bdcSMaxim Levitsky uint32_t val; 1059557d2bdcSMaxim Levitsky 1060557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1061557d2bdcSMaxim Levitsky val = luks->header.key_slots[slot_idx].active; 1062557d2bdcSMaxim Levitsky return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1063557d2bdcSMaxim Levitsky } 1064557d2bdcSMaxim Levitsky 1065557d2bdcSMaxim Levitsky /* 1066557d2bdcSMaxim Levitsky * Returns the number of slots that are marked as active 1067557d2bdcSMaxim Levitsky * (slots that contain encrypted copy of the master key) 1068557d2bdcSMaxim Levitsky */ 1069557d2bdcSMaxim Levitsky static unsigned int 1070557d2bdcSMaxim Levitsky qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) 1071557d2bdcSMaxim Levitsky { 1072557d2bdcSMaxim Levitsky size_t i = 0; 1073557d2bdcSMaxim Levitsky unsigned int ret = 0; 1074557d2bdcSMaxim Levitsky 1075557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1076557d2bdcSMaxim Levitsky if (qcrypto_block_luks_slot_active(luks, i)) { 1077557d2bdcSMaxim Levitsky ret++; 1078557d2bdcSMaxim Levitsky } 1079557d2bdcSMaxim Levitsky } 1080557d2bdcSMaxim Levitsky return ret; 1081557d2bdcSMaxim Levitsky } 1082557d2bdcSMaxim Levitsky 1083557d2bdcSMaxim Levitsky /* 1084557d2bdcSMaxim Levitsky * Finds first key slot which is not active 1085557d2bdcSMaxim Levitsky * Returns the key slot index, or -1 if it doesn't exist 1086557d2bdcSMaxim Levitsky */ 1087557d2bdcSMaxim Levitsky static int 1088557d2bdcSMaxim Levitsky qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) 1089557d2bdcSMaxim Levitsky { 1090557d2bdcSMaxim Levitsky size_t i; 1091557d2bdcSMaxim Levitsky 1092557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1093557d2bdcSMaxim Levitsky if (!qcrypto_block_luks_slot_active(luks, i)) { 1094557d2bdcSMaxim Levitsky return i; 1095557d2bdcSMaxim Levitsky } 1096557d2bdcSMaxim Levitsky } 1097557d2bdcSMaxim Levitsky return -1; 1098557d2bdcSMaxim Levitsky } 1099557d2bdcSMaxim Levitsky 1100557d2bdcSMaxim Levitsky /* 1101557d2bdcSMaxim Levitsky * Erases an keyslot given its index 1102557d2bdcSMaxim Levitsky * Returns: 1103557d2bdcSMaxim Levitsky * 0 if the keyslot was erased successfully 1104557d2bdcSMaxim Levitsky * -1 if a error occurred while erasing the keyslot 1105557d2bdcSMaxim Levitsky * 1106557d2bdcSMaxim Levitsky */ 1107557d2bdcSMaxim Levitsky static int 1108557d2bdcSMaxim Levitsky qcrypto_block_luks_erase_key(QCryptoBlock *block, 1109557d2bdcSMaxim Levitsky unsigned int slot_idx, 1110557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1111557d2bdcSMaxim Levitsky void *opaque, 1112557d2bdcSMaxim Levitsky Error **errp) 1113557d2bdcSMaxim Levitsky { 1114557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1115557d2bdcSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot; 1116557d2bdcSMaxim Levitsky g_autofree uint8_t *garbagesplitkey = NULL; 1117557d2bdcSMaxim Levitsky size_t splitkeylen; 1118557d2bdcSMaxim Levitsky size_t i; 1119557d2bdcSMaxim Levitsky Error *local_err = NULL; 1120557d2bdcSMaxim Levitsky int ret; 1121557d2bdcSMaxim Levitsky 1122557d2bdcSMaxim Levitsky assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1123557d2bdcSMaxim Levitsky slot = &luks->header.key_slots[slot_idx]; 1124557d2bdcSMaxim Levitsky 1125557d2bdcSMaxim Levitsky splitkeylen = luks->header.master_key_len * slot->stripes; 1126557d2bdcSMaxim Levitsky assert(splitkeylen > 0); 1127557d2bdcSMaxim Levitsky 1128557d2bdcSMaxim Levitsky garbagesplitkey = g_new0(uint8_t, splitkeylen); 1129557d2bdcSMaxim Levitsky 1130557d2bdcSMaxim Levitsky /* Reset the key slot header */ 1131557d2bdcSMaxim Levitsky memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); 1132557d2bdcSMaxim Levitsky slot->iterations = 0; 1133557d2bdcSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 1134557d2bdcSMaxim Levitsky 1135557d2bdcSMaxim Levitsky ret = qcrypto_block_luks_store_header(block, writefunc, 1136557d2bdcSMaxim Levitsky opaque, &local_err); 1137557d2bdcSMaxim Levitsky 1138557d2bdcSMaxim Levitsky if (ret < 0) { 1139557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1140557d2bdcSMaxim Levitsky } 1141557d2bdcSMaxim Levitsky /* 1142557d2bdcSMaxim Levitsky * Now try to erase the key material, even if the header 1143557d2bdcSMaxim Levitsky * update failed 1144557d2bdcSMaxim Levitsky */ 1145557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { 1146557d2bdcSMaxim Levitsky if (qcrypto_random_bytes(garbagesplitkey, 1147557d2bdcSMaxim Levitsky splitkeylen, &local_err) < 0) { 1148557d2bdcSMaxim Levitsky /* 1149557d2bdcSMaxim Levitsky * If we failed to get the random data, still write 1150557d2bdcSMaxim Levitsky * at least zeros to the key slot at least once 1151557d2bdcSMaxim Levitsky */ 1152557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1153557d2bdcSMaxim Levitsky 1154557d2bdcSMaxim Levitsky if (i > 0) { 1155557d2bdcSMaxim Levitsky return -1; 1156557d2bdcSMaxim Levitsky } 1157557d2bdcSMaxim Levitsky } 1158557d2bdcSMaxim Levitsky if (writefunc(block, 1159557d2bdcSMaxim Levitsky slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 1160557d2bdcSMaxim Levitsky garbagesplitkey, 1161557d2bdcSMaxim Levitsky splitkeylen, 1162557d2bdcSMaxim Levitsky opaque, 1163757dda54SAlberto Faria &local_err) < 0) { 1164557d2bdcSMaxim Levitsky error_propagate(errp, local_err); 1165557d2bdcSMaxim Levitsky return -1; 1166557d2bdcSMaxim Levitsky } 1167557d2bdcSMaxim Levitsky } 1168557d2bdcSMaxim Levitsky return ret; 1169557d2bdcSMaxim Levitsky } 11703e308f20SDaniel P. Berrange 11713e308f20SDaniel P. Berrange static int 11723e308f20SDaniel P. Berrange qcrypto_block_luks_open(QCryptoBlock *block, 11733e308f20SDaniel P. Berrange QCryptoBlockOpenOptions *options, 11741cd9a787SDaniel P. Berrange const char *optprefix, 11753e308f20SDaniel P. Berrange QCryptoBlockReadFunc readfunc, 11763e308f20SDaniel P. Berrange void *opaque, 11773e308f20SDaniel P. Berrange unsigned int flags, 1178c972fa12SVladimir Sementsov-Ogievskiy size_t n_threads, 11793e308f20SDaniel P. Berrange Error **errp) 11803e308f20SDaniel P. Berrange { 11819d80e59dSMaxim Levitsky QCryptoBlockLUKS *luks = NULL; 118257b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 118357b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 11843e308f20SDaniel P. Berrange 11853e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 11863e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 11871cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 11881cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 11893e308f20SDaniel P. Berrange return -1; 11903e308f20SDaniel P. Berrange } 11913e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8( 11923e308f20SDaniel P. Berrange options->u.luks.key_secret, errp); 11933e308f20SDaniel P. Berrange if (!password) { 11943e308f20SDaniel P. Berrange return -1; 11953e308f20SDaniel P. Berrange } 11963e308f20SDaniel P. Berrange } 11973e308f20SDaniel P. Berrange 11983e308f20SDaniel P. Berrange luks = g_new0(QCryptoBlockLUKS, 1); 11993e308f20SDaniel P. Berrange block->opaque = luks; 1200557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 12013e308f20SDaniel P. Berrange 1202dde2c5afSMaxim Levitsky if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 12033e308f20SDaniel P. Berrange goto fail; 12043e308f20SDaniel P. Berrange } 12053e308f20SDaniel P. Berrange 12069fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_check_header(luks, errp) < 0) { 12073e308f20SDaniel P. Berrange goto fail; 12083e308f20SDaniel P. Berrange } 12093e308f20SDaniel P. Berrange 12109fa9c1c2SMaxim Levitsky if (qcrypto_block_luks_parse_header(luks, errp) < 0) { 12113e308f20SDaniel P. Berrange goto fail; 12123e308f20SDaniel P. Berrange } 12133e308f20SDaniel P. Berrange 12143e308f20SDaniel P. Berrange if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) { 12153e308f20SDaniel P. Berrange /* Try to find which key slot our password is valid for 12163e308f20SDaniel P. Berrange * and unlock the master key from that slot. 12173e308f20SDaniel P. Berrange */ 12181ddd52e4SMaxim Levitsky 12191ddd52e4SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 12201ddd52e4SMaxim Levitsky 12213e308f20SDaniel P. Berrange if (qcrypto_block_luks_find_key(block, 12223e308f20SDaniel P. Berrange password, 12231ddd52e4SMaxim Levitsky masterkey, 12243e308f20SDaniel P. Berrange readfunc, opaque, 12253e308f20SDaniel P. Berrange errp) < 0) { 12263e308f20SDaniel P. Berrange goto fail; 12273e308f20SDaniel P. Berrange } 12283e308f20SDaniel P. Berrange 12293e308f20SDaniel P. Berrange /* We have a valid master key now, so can setup the 12303e308f20SDaniel P. Berrange * block device payload decryption objects 12313e308f20SDaniel P. Berrange */ 12329d80e59dSMaxim Levitsky block->kdfhash = luks->hash_alg; 12339d80e59dSMaxim Levitsky block->niv = qcrypto_cipher_get_iv_len(luks->cipher_alg, 12349d80e59dSMaxim Levitsky luks->cipher_mode); 12359d80e59dSMaxim Levitsky 12369d80e59dSMaxim Levitsky block->ivgen = qcrypto_ivgen_new(luks->ivgen_alg, 12379d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 12389d80e59dSMaxim Levitsky luks->ivgen_hash_alg, 12391ddd52e4SMaxim Levitsky masterkey, 12401ddd52e4SMaxim Levitsky luks->header.master_key_len, 12413e308f20SDaniel P. Berrange errp); 12423e308f20SDaniel P. Berrange if (!block->ivgen) { 12433e308f20SDaniel P. Berrange goto fail; 12443e308f20SDaniel P. Berrange } 12453e308f20SDaniel P. Berrange 124661dd8a9aSMaxim Levitsky if (qcrypto_block_init_cipher(block, 12479d80e59dSMaxim Levitsky luks->cipher_alg, 12489d80e59dSMaxim Levitsky luks->cipher_mode, 12491ddd52e4SMaxim Levitsky masterkey, 12501ddd52e4SMaxim Levitsky luks->header.master_key_len, 12511ddd52e4SMaxim Levitsky n_threads, 125261dd8a9aSMaxim Levitsky errp) < 0) { 12533e308f20SDaniel P. Berrange goto fail; 12543e308f20SDaniel P. Berrange } 12553e308f20SDaniel P. Berrange } 12563e308f20SDaniel P. Berrange 1257850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1258f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1259850f49deSDaniel P. Berrange block->sector_size; 12603e308f20SDaniel P. Berrange 12613e308f20SDaniel P. Berrange return 0; 12623e308f20SDaniel P. Berrange 12633e308f20SDaniel P. Berrange fail: 1264c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 12653e308f20SDaniel P. Berrange qcrypto_ivgen_free(block->ivgen); 1266557d2bdcSMaxim Levitsky g_free(luks->secret); 12673e308f20SDaniel P. Berrange g_free(luks); 126861dd8a9aSMaxim Levitsky return -1; 12693e308f20SDaniel P. Berrange } 12703e308f20SDaniel P. Berrange 12713e308f20SDaniel P. Berrange 12722ef950f9SFam Zheng static void 12732ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(uint8_t *uuidstr) 12743e308f20SDaniel P. Berrange { 12752ef950f9SFam Zheng QemuUUID uuid; 12762ef950f9SFam Zheng qemu_uuid_generate(&uuid); 12772ef950f9SFam Zheng qemu_uuid_unparse(&uuid, (char *)uuidstr); 12783e308f20SDaniel P. Berrange } 12793e308f20SDaniel P. Berrange 12803e308f20SDaniel P. Berrange static int 12813e308f20SDaniel P. Berrange qcrypto_block_luks_create(QCryptoBlock *block, 12823e308f20SDaniel P. Berrange QCryptoBlockCreateOptions *options, 12831cd9a787SDaniel P. Berrange const char *optprefix, 12843e308f20SDaniel P. Berrange QCryptoBlockInitFunc initfunc, 12853e308f20SDaniel P. Berrange QCryptoBlockWriteFunc writefunc, 12863e308f20SDaniel P. Berrange void *opaque, 12873e308f20SDaniel P. Berrange Error **errp) 12883e308f20SDaniel P. Berrange { 12893e308f20SDaniel P. Berrange QCryptoBlockLUKS *luks; 12903e308f20SDaniel P. Berrange QCryptoBlockCreateOptionsLUKS luks_opts; 12913e308f20SDaniel P. Berrange Error *local_err = NULL; 129257b9f113SDaniel P. Berrangé g_autofree uint8_t *masterkey = NULL; 1293bd56a55aSMaxim Levitsky size_t header_sectors; 1294bd56a55aSMaxim Levitsky size_t split_key_sectors; 12953e308f20SDaniel P. Berrange size_t i; 129657b9f113SDaniel P. Berrangé g_autofree char *password = NULL; 12973e308f20SDaniel P. Berrange const char *cipher_alg; 12983e308f20SDaniel P. Berrange const char *cipher_mode; 12993e308f20SDaniel P. Berrange const char *ivgen_alg; 13003e308f20SDaniel P. Berrange const char *ivgen_hash_alg = NULL; 13013e308f20SDaniel P. Berrange const char *hash_alg; 130257b9f113SDaniel P. Berrangé g_autofree char *cipher_mode_spec = NULL; 130359b060beSDaniel P. Berrange uint64_t iters; 13043e308f20SDaniel P. Berrange 13053e308f20SDaniel P. Berrange memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 13063bd18890SDaniel P. Berrange if (!luks_opts.has_iter_time) { 1307557d2bdcSMaxim Levitsky luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 13083bd18890SDaniel P. Berrange } 13093e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_alg) { 13103e308f20SDaniel P. Berrange luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; 13113e308f20SDaniel P. Berrange } 13123e308f20SDaniel P. Berrange if (!luks_opts.has_cipher_mode) { 13133e308f20SDaniel P. Berrange luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; 13143e308f20SDaniel P. Berrange } 13153e308f20SDaniel P. Berrange if (!luks_opts.has_ivgen_alg) { 13163e308f20SDaniel P. Berrange luks_opts.ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64; 13173e308f20SDaniel P. Berrange } 13183e308f20SDaniel P. Berrange if (!luks_opts.has_hash_alg) { 13193e308f20SDaniel P. Berrange luks_opts.hash_alg = QCRYPTO_HASH_ALG_SHA256; 13203e308f20SDaniel P. Berrange } 13218b7cdba3SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 13228b7cdba3SDaniel P. Berrange if (!luks_opts.has_ivgen_hash_alg) { 13238b7cdba3SDaniel P. Berrange luks_opts.ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256; 13248b7cdba3SDaniel P. Berrange luks_opts.has_ivgen_hash_alg = true; 13258b7cdba3SDaniel P. Berrange } 13268b7cdba3SDaniel P. Berrange } 13279d80e59dSMaxim Levitsky 13289d80e59dSMaxim Levitsky luks = g_new0(QCryptoBlockLUKS, 1); 13299d80e59dSMaxim Levitsky block->opaque = luks; 13309d80e59dSMaxim Levitsky 13319d80e59dSMaxim Levitsky luks->cipher_alg = luks_opts.cipher_alg; 13329d80e59dSMaxim Levitsky luks->cipher_mode = luks_opts.cipher_mode; 13339d80e59dSMaxim Levitsky luks->ivgen_alg = luks_opts.ivgen_alg; 13349d80e59dSMaxim Levitsky luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg; 13359d80e59dSMaxim Levitsky luks->hash_alg = luks_opts.hash_alg; 13369d80e59dSMaxim Levitsky 13379d80e59dSMaxim Levitsky 13388b7cdba3SDaniel P. Berrange /* Note we're allowing ivgen_hash_alg to be set even for 13398b7cdba3SDaniel P. Berrange * non-essiv iv generators that don't need a hash. It will 13408b7cdba3SDaniel P. Berrange * be silently ignored, for compatibility with dm-crypt */ 13413e308f20SDaniel P. Berrange 13423e308f20SDaniel P. Berrange if (!options->u.luks.key_secret) { 13431cd9a787SDaniel P. Berrange error_setg(errp, "Parameter '%skey-secret' is required for cipher", 13441cd9a787SDaniel P. Berrange optprefix ? optprefix : ""); 13459d80e59dSMaxim Levitsky goto error; 13463e308f20SDaniel P. Berrange } 1347557d2bdcSMaxim Levitsky luks->secret = g_strdup(options->u.luks.key_secret); 1348557d2bdcSMaxim Levitsky 13493e308f20SDaniel P. Berrange password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 13503e308f20SDaniel P. Berrange if (!password) { 13519d80e59dSMaxim Levitsky goto error; 13523e308f20SDaniel P. Berrange } 13533e308f20SDaniel P. Berrange 13543e308f20SDaniel P. Berrange 13553e308f20SDaniel P. Berrange memcpy(luks->header.magic, qcrypto_block_luks_magic, 13563e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_MAGIC_LEN); 13573e308f20SDaniel P. Berrange 13583e308f20SDaniel P. Berrange /* We populate the header in native endianness initially and 13593e308f20SDaniel P. Berrange * then convert everything to big endian just before writing 13603e308f20SDaniel P. Berrange * it out to disk 13613e308f20SDaniel P. Berrange */ 13623e308f20SDaniel P. Berrange luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION; 13632ef950f9SFam Zheng qcrypto_block_luks_uuid_gen(luks->header.uuid); 13643e308f20SDaniel P. Berrange 13653e308f20SDaniel P. Berrange cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg, 13663e308f20SDaniel P. Berrange errp); 13673e308f20SDaniel P. Berrange if (!cipher_alg) { 13683e308f20SDaniel P. Berrange goto error; 13693e308f20SDaniel P. Berrange } 13703e308f20SDaniel P. Berrange 1371977c736fSMarkus Armbruster cipher_mode = QCryptoCipherMode_str(luks_opts.cipher_mode); 1372977c736fSMarkus Armbruster ivgen_alg = QCryptoIVGenAlgorithm_str(luks_opts.ivgen_alg); 13733e308f20SDaniel P. Berrange if (luks_opts.has_ivgen_hash_alg) { 1374977c736fSMarkus Armbruster ivgen_hash_alg = QCryptoHashAlgorithm_str(luks_opts.ivgen_hash_alg); 13753e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s:%s", cipher_mode, ivgen_alg, 13763e308f20SDaniel P. Berrange ivgen_hash_alg); 13773e308f20SDaniel P. Berrange } else { 13783e308f20SDaniel P. Berrange cipher_mode_spec = g_strdup_printf("%s-%s", cipher_mode, ivgen_alg); 13793e308f20SDaniel P. Berrange } 1380977c736fSMarkus Armbruster hash_alg = QCryptoHashAlgorithm_str(luks_opts.hash_alg); 13813e308f20SDaniel P. Berrange 13823e308f20SDaniel P. Berrange 13833e308f20SDaniel P. Berrange if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) { 13843e308f20SDaniel P. Berrange error_setg(errp, "Cipher name '%s' is too long for LUKS header", 13853e308f20SDaniel P. Berrange cipher_alg); 13863e308f20SDaniel P. Berrange goto error; 13873e308f20SDaniel P. Berrange } 13883e308f20SDaniel P. Berrange if (strlen(cipher_mode_spec) >= QCRYPTO_BLOCK_LUKS_CIPHER_MODE_LEN) { 13893e308f20SDaniel P. Berrange error_setg(errp, "Cipher mode '%s' is too long for LUKS header", 13903e308f20SDaniel P. Berrange cipher_mode_spec); 13913e308f20SDaniel P. Berrange goto error; 13923e308f20SDaniel P. Berrange } 13933e308f20SDaniel P. Berrange if (strlen(hash_alg) >= QCRYPTO_BLOCK_LUKS_HASH_SPEC_LEN) { 13943e308f20SDaniel P. Berrange error_setg(errp, "Hash name '%s' is too long for LUKS header", 13953e308f20SDaniel P. Berrange hash_alg); 13963e308f20SDaniel P. Berrange goto error; 13973e308f20SDaniel P. Berrange } 13983e308f20SDaniel P. Berrange 13993e308f20SDaniel P. Berrange if (luks_opts.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 14009d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = 14019d80e59dSMaxim Levitsky qcrypto_block_luks_essiv_cipher(luks_opts.cipher_alg, 14023e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 14033e308f20SDaniel P. Berrange &local_err); 14043e308f20SDaniel P. Berrange if (local_err) { 14053e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14063e308f20SDaniel P. Berrange goto error; 14073e308f20SDaniel P. Berrange } 14083e308f20SDaniel P. Berrange } else { 14099d80e59dSMaxim Levitsky luks->ivgen_cipher_alg = luks_opts.cipher_alg; 14103e308f20SDaniel P. Berrange } 14113e308f20SDaniel P. Berrange 14123e308f20SDaniel P. Berrange strcpy(luks->header.cipher_name, cipher_alg); 14133e308f20SDaniel P. Berrange strcpy(luks->header.cipher_mode, cipher_mode_spec); 14143e308f20SDaniel P. Berrange strcpy(luks->header.hash_spec, hash_alg); 14153e308f20SDaniel P. Berrange 1416f0d3c362SMaxim Levitsky luks->header.master_key_len = 1417f0d3c362SMaxim Levitsky qcrypto_cipher_get_key_len(luks_opts.cipher_alg); 1418f0d3c362SMaxim Levitsky 14193e308f20SDaniel P. Berrange if (luks_opts.cipher_mode == QCRYPTO_CIPHER_MODE_XTS) { 1420f0d3c362SMaxim Levitsky luks->header.master_key_len *= 2; 14213e308f20SDaniel P. Berrange } 14223e308f20SDaniel P. Berrange 14233e308f20SDaniel P. Berrange /* Generate the salt used for hashing the master key 14243e308f20SDaniel P. Berrange * with PBKDF later 14253e308f20SDaniel P. Berrange */ 14263e308f20SDaniel P. Berrange if (qcrypto_random_bytes(luks->header.master_key_salt, 14273e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 14283e308f20SDaniel P. Berrange errp) < 0) { 14293e308f20SDaniel P. Berrange goto error; 14303e308f20SDaniel P. Berrange } 14313e308f20SDaniel P. Berrange 14323e308f20SDaniel P. Berrange /* Generate random master key */ 1433f0d3c362SMaxim Levitsky masterkey = g_new0(uint8_t, luks->header.master_key_len); 14343e308f20SDaniel P. Berrange if (qcrypto_random_bytes(masterkey, 1435f0d3c362SMaxim Levitsky luks->header.master_key_len, errp) < 0) { 14363e308f20SDaniel P. Berrange goto error; 14373e308f20SDaniel P. Berrange } 14383e308f20SDaniel P. Berrange 14393e308f20SDaniel P. Berrange 14403e308f20SDaniel P. Berrange /* Setup the block device payload encryption objects */ 1441c972fa12SVladimir Sementsov-Ogievskiy if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg, 1442c972fa12SVladimir Sementsov-Ogievskiy luks_opts.cipher_mode, masterkey, 1443f0d3c362SMaxim Levitsky luks->header.master_key_len, 1, errp) < 0) { 14443e308f20SDaniel P. Berrange goto error; 14453e308f20SDaniel P. Berrange } 14463e308f20SDaniel P. Berrange 14473e308f20SDaniel P. Berrange block->kdfhash = luks_opts.hash_alg; 14483e308f20SDaniel P. Berrange block->niv = qcrypto_cipher_get_iv_len(luks_opts.cipher_alg, 14493e308f20SDaniel P. Berrange luks_opts.cipher_mode); 14503e308f20SDaniel P. Berrange block->ivgen = qcrypto_ivgen_new(luks_opts.ivgen_alg, 14519d80e59dSMaxim Levitsky luks->ivgen_cipher_alg, 14523e308f20SDaniel P. Berrange luks_opts.ivgen_hash_alg, 1453f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14543e308f20SDaniel P. Berrange errp); 14553e308f20SDaniel P. Berrange 14563e308f20SDaniel P. Berrange if (!block->ivgen) { 14573e308f20SDaniel P. Berrange goto error; 14583e308f20SDaniel P. Berrange } 14593e308f20SDaniel P. Berrange 14603e308f20SDaniel P. Berrange 14613e308f20SDaniel P. Berrange /* Determine how many iterations we need to hash the master 14623e308f20SDaniel P. Berrange * key, in order to have 1 second of compute time used 14633e308f20SDaniel P. Berrange */ 146459b060beSDaniel P. Berrange iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg, 1465f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 14663e308f20SDaniel P. Berrange luks->header.master_key_salt, 14673e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 1468e74aabcfSDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 14693e308f20SDaniel P. Berrange &local_err); 14703e308f20SDaniel P. Berrange if (local_err) { 14713e308f20SDaniel P. Berrange error_propagate(errp, local_err); 14723e308f20SDaniel P. Berrange goto error; 14733e308f20SDaniel P. Berrange } 14743e308f20SDaniel P. Berrange 14753bd18890SDaniel P. Berrange if (iters > (ULLONG_MAX / luks_opts.iter_time)) { 14763bd18890SDaniel P. Berrange error_setg_errno(errp, ERANGE, 14773bd18890SDaniel P. Berrange "PBKDF iterations %llu too large to scale", 14783bd18890SDaniel P. Berrange (unsigned long long)iters); 14793bd18890SDaniel P. Berrange goto error; 14803bd18890SDaniel P. Berrange } 14813bd18890SDaniel P. Berrange 14823bd18890SDaniel P. Berrange /* iter_time was in millis, but count_iters reported for secs */ 14833bd18890SDaniel P. Berrange iters = iters * luks_opts.iter_time / 1000; 14843bd18890SDaniel P. Berrange 14853e308f20SDaniel P. Berrange /* Why /= 8 ? That matches cryptsetup, but there's no 14863e308f20SDaniel P. Berrange * explanation why they chose /= 8... Probably so that 14873e308f20SDaniel P. Berrange * if all 8 keyslots are active we only spend 1 second 14883e308f20SDaniel P. Berrange * in total time to check all keys */ 148959b060beSDaniel P. Berrange iters /= 8; 149059b060beSDaniel P. Berrange if (iters > UINT32_MAX) { 149159b060beSDaniel P. Berrange error_setg_errno(errp, ERANGE, 149259b060beSDaniel P. Berrange "PBKDF iterations %llu larger than %u", 149359b060beSDaniel P. Berrange (unsigned long long)iters, UINT32_MAX); 149459b060beSDaniel P. Berrange goto error; 149559b060beSDaniel P. Berrange } 149659b060beSDaniel P. Berrange iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS); 149759b060beSDaniel P. Berrange luks->header.master_key_iterations = iters; 14983e308f20SDaniel P. Berrange 14993e308f20SDaniel P. Berrange /* Hash the master key, saving the result in the LUKS 15003e308f20SDaniel P. Berrange * header. This hash is used when opening the encrypted 15013e308f20SDaniel P. Berrange * device to verify that the user password unlocked a 15023e308f20SDaniel P. Berrange * valid master key 15033e308f20SDaniel P. Berrange */ 15043e308f20SDaniel P. Berrange if (qcrypto_pbkdf2(luks_opts.hash_alg, 1505f0d3c362SMaxim Levitsky masterkey, luks->header.master_key_len, 15063e308f20SDaniel P. Berrange luks->header.master_key_salt, 15073e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SALT_LEN, 15083e308f20SDaniel P. Berrange luks->header.master_key_iterations, 15093e308f20SDaniel P. Berrange luks->header.master_key_digest, 15103e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_DIGEST_LEN, 15113e308f20SDaniel P. Berrange errp) < 0) { 15123e308f20SDaniel P. Berrange goto error; 15133e308f20SDaniel P. Berrange } 15143e308f20SDaniel P. Berrange 1515bd56a55aSMaxim Levitsky /* start with the sector that follows the header*/ 1516bd56a55aSMaxim Levitsky header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET / 1517bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 15183e308f20SDaniel P. Berrange 1519bd56a55aSMaxim Levitsky split_key_sectors = 1520bd56a55aSMaxim Levitsky qcrypto_block_luks_splitkeylen_sectors(luks, 1521bd56a55aSMaxim Levitsky header_sectors, 1522bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_STRIPES); 1523bd56a55aSMaxim Levitsky 15243e308f20SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1525bd56a55aSMaxim Levitsky QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[i]; 1526bd56a55aSMaxim Levitsky slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 15273e308f20SDaniel P. Berrange 1528bd56a55aSMaxim Levitsky slot->key_offset_sector = header_sectors + i * split_key_sectors; 1529bd56a55aSMaxim Levitsky slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES; 15303e308f20SDaniel P. Berrange } 15313e308f20SDaniel P. Berrange 15323e308f20SDaniel P. Berrange /* The total size of the LUKS headers is the partition header + key 15333e308f20SDaniel P. Berrange * slot headers, rounded up to the nearest sector, combined with 15343e308f20SDaniel P. Berrange * the size of each master key material region, also rounded up 15353e308f20SDaniel P. Berrange * to the nearest sector */ 1536bd56a55aSMaxim Levitsky luks->header.payload_offset_sector = header_sectors + 1537bd56a55aSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors; 15383e308f20SDaniel P. Berrange 1539850f49deSDaniel P. Berrange block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 1540f0d3c362SMaxim Levitsky block->payload_offset = luks->header.payload_offset_sector * 1541850f49deSDaniel P. Berrange block->sector_size; 15423e308f20SDaniel P. Berrange 15433e308f20SDaniel P. Berrange /* Reserve header space to match payload offset */ 1544e4a3507eSDaniel P. Berrange initfunc(block, block->payload_offset, opaque, &local_err); 15453e308f20SDaniel P. Berrange if (local_err) { 15463e308f20SDaniel P. Berrange error_propagate(errp, local_err); 15473e308f20SDaniel P. Berrange goto error; 15483e308f20SDaniel P. Berrange } 15493e308f20SDaniel P. Berrange 15503e308f20SDaniel P. Berrange 15513994a7c9SMaxim Levitsky /* populate the slot 0 with the password encrypted master key*/ 15523994a7c9SMaxim Levitsky /* This will also store the header */ 15533994a7c9SMaxim Levitsky if (qcrypto_block_luks_store_key(block, 15543994a7c9SMaxim Levitsky 0, 15553994a7c9SMaxim Levitsky password, 15563994a7c9SMaxim Levitsky masterkey, 15573994a7c9SMaxim Levitsky luks_opts.iter_time, 15583994a7c9SMaxim Levitsky writefunc, 1559e4a3507eSDaniel P. Berrange opaque, 15603994a7c9SMaxim Levitsky errp) < 0) { 15613e308f20SDaniel P. Berrange goto error; 15623e308f20SDaniel P. Berrange } 15633e308f20SDaniel P. Berrange 1564f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15653e308f20SDaniel P. Berrange 15663e308f20SDaniel P. Berrange return 0; 15673e308f20SDaniel P. Berrange 15683e308f20SDaniel P. Berrange error: 15693e308f20SDaniel P. Berrange if (masterkey) { 1570f0d3c362SMaxim Levitsky memset(masterkey, 0, luks->header.master_key_len); 15713e308f20SDaniel P. Berrange } 15723e308f20SDaniel P. Berrange 1573c972fa12SVladimir Sementsov-Ogievskiy qcrypto_block_free_cipher(block); 1574b640adcaSVladimir Sementsov-Ogievskiy qcrypto_ivgen_free(block->ivgen); 1575b640adcaSVladimir Sementsov-Ogievskiy 1576557d2bdcSMaxim Levitsky g_free(luks->secret); 15773e308f20SDaniel P. Berrange g_free(luks); 15783e308f20SDaniel P. Berrange return -1; 15793e308f20SDaniel P. Berrange } 15803e308f20SDaniel P. Berrange 1581557d2bdcSMaxim Levitsky static int 1582557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, 1583557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1584557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1585557d2bdcSMaxim Levitsky void *opaque, 1586557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1587557d2bdcSMaxim Levitsky bool force, 1588557d2bdcSMaxim Levitsky Error **errp) 1589557d2bdcSMaxim Levitsky { 1590557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1591557d2bdcSMaxim Levitsky uint64_t iter_time = opts_luks->has_iter_time ? 1592557d2bdcSMaxim Levitsky opts_luks->iter_time : 1593557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1594557d2bdcSMaxim Levitsky int keyslot; 1595557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1596557d2bdcSMaxim Levitsky g_autofree char *new_password = NULL; 1597557d2bdcSMaxim Levitsky g_autofree uint8_t *master_key = NULL; 1598557d2bdcSMaxim Levitsky 159916110c8bSMarkus Armbruster char *secret = opts_luks->secret ?: luks->secret; 1600557d2bdcSMaxim Levitsky 160116110c8bSMarkus Armbruster if (!opts_luks->new_secret) { 1602557d2bdcSMaxim Levitsky error_setg(errp, "'new-secret' is required to activate a keyslot"); 1603557d2bdcSMaxim Levitsky return -1; 1604557d2bdcSMaxim Levitsky } 160516110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1606557d2bdcSMaxim Levitsky error_setg(errp, 1607557d2bdcSMaxim Levitsky "'old-secret' must not be given when activating keyslots"); 1608557d2bdcSMaxim Levitsky return -1; 1609557d2bdcSMaxim Levitsky } 1610557d2bdcSMaxim Levitsky 1611557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1612557d2bdcSMaxim Levitsky keyslot = opts_luks->keyslot; 1613557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1614557d2bdcSMaxim Levitsky error_setg(errp, 1615557d2bdcSMaxim Levitsky "Invalid keyslot %u specified, must be between 0 and %u", 1616557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1617557d2bdcSMaxim Levitsky return -1; 1618557d2bdcSMaxim Levitsky } 1619557d2bdcSMaxim Levitsky } else { 1620557d2bdcSMaxim Levitsky keyslot = qcrypto_block_luks_find_free_keyslot(luks); 1621557d2bdcSMaxim Levitsky if (keyslot == -1) { 1622557d2bdcSMaxim Levitsky error_setg(errp, 1623557d2bdcSMaxim Levitsky "Can't add a keyslot - all keyslots are in use"); 1624557d2bdcSMaxim Levitsky return -1; 1625557d2bdcSMaxim Levitsky } 1626557d2bdcSMaxim Levitsky } 1627557d2bdcSMaxim Levitsky 1628557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { 1629557d2bdcSMaxim Levitsky error_setg(errp, 1630557d2bdcSMaxim Levitsky "Refusing to overwrite active keyslot %i - " 1631557d2bdcSMaxim Levitsky "please erase it first", 1632557d2bdcSMaxim Levitsky keyslot); 1633557d2bdcSMaxim Levitsky return -1; 1634557d2bdcSMaxim Levitsky } 1635557d2bdcSMaxim Levitsky 1636557d2bdcSMaxim Levitsky /* Locate the password that will be used to retrieve the master key */ 1637557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(secret, errp); 1638557d2bdcSMaxim Levitsky if (!old_password) { 1639557d2bdcSMaxim Levitsky return -1; 1640557d2bdcSMaxim Levitsky } 1641557d2bdcSMaxim Levitsky 1642557d2bdcSMaxim Levitsky /* Retrieve the master key */ 1643557d2bdcSMaxim Levitsky master_key = g_new0(uint8_t, luks->header.master_key_len); 1644557d2bdcSMaxim Levitsky 1645557d2bdcSMaxim Levitsky if (qcrypto_block_luks_find_key(block, old_password, master_key, 1646557d2bdcSMaxim Levitsky readfunc, opaque, errp) < 0) { 1647557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to retrieve the master key"); 1648557d2bdcSMaxim Levitsky return -1; 1649557d2bdcSMaxim Levitsky } 1650557d2bdcSMaxim Levitsky 1651557d2bdcSMaxim Levitsky /* Locate the new password*/ 1652557d2bdcSMaxim Levitsky new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); 1653557d2bdcSMaxim Levitsky if (!new_password) { 1654557d2bdcSMaxim Levitsky return -1; 1655557d2bdcSMaxim Levitsky } 1656557d2bdcSMaxim Levitsky 1657557d2bdcSMaxim Levitsky /* Now set the new keyslots */ 1658557d2bdcSMaxim Levitsky if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, 1659557d2bdcSMaxim Levitsky iter_time, writefunc, opaque, errp)) { 1660557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to write to keyslot %i", keyslot); 1661557d2bdcSMaxim Levitsky return -1; 1662557d2bdcSMaxim Levitsky } 1663557d2bdcSMaxim Levitsky return 0; 1664557d2bdcSMaxim Levitsky } 1665557d2bdcSMaxim Levitsky 1666557d2bdcSMaxim Levitsky static int 1667557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, 1668557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1669557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1670557d2bdcSMaxim Levitsky void *opaque, 1671557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks, 1672557d2bdcSMaxim Levitsky bool force, 1673557d2bdcSMaxim Levitsky Error **errp) 1674557d2bdcSMaxim Levitsky { 1675557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1676557d2bdcSMaxim Levitsky g_autofree uint8_t *tmpkey = NULL; 1677557d2bdcSMaxim Levitsky g_autofree char *old_password = NULL; 1678557d2bdcSMaxim Levitsky 167916110c8bSMarkus Armbruster if (opts_luks->new_secret) { 1680557d2bdcSMaxim Levitsky error_setg(errp, 1681557d2bdcSMaxim Levitsky "'new-secret' must not be given when erasing keyslots"); 1682557d2bdcSMaxim Levitsky return -1; 1683557d2bdcSMaxim Levitsky } 1684557d2bdcSMaxim Levitsky if (opts_luks->has_iter_time) { 1685557d2bdcSMaxim Levitsky error_setg(errp, 1686557d2bdcSMaxim Levitsky "'iter-time' must not be given when erasing keyslots"); 1687557d2bdcSMaxim Levitsky return -1; 1688557d2bdcSMaxim Levitsky } 168916110c8bSMarkus Armbruster if (opts_luks->secret) { 1690557d2bdcSMaxim Levitsky error_setg(errp, 1691557d2bdcSMaxim Levitsky "'secret' must not be given when erasing keyslots"); 1692557d2bdcSMaxim Levitsky return -1; 1693557d2bdcSMaxim Levitsky } 1694557d2bdcSMaxim Levitsky 1695557d2bdcSMaxim Levitsky /* Load the old password if given */ 169616110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1697557d2bdcSMaxim Levitsky old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, 1698557d2bdcSMaxim Levitsky errp); 1699557d2bdcSMaxim Levitsky if (!old_password) { 1700557d2bdcSMaxim Levitsky return -1; 1701557d2bdcSMaxim Levitsky } 1702557d2bdcSMaxim Levitsky 1703557d2bdcSMaxim Levitsky /* 1704557d2bdcSMaxim Levitsky * Allocate a temporary key buffer that we will need when 1705557d2bdcSMaxim Levitsky * checking if slot matches the given old password 1706557d2bdcSMaxim Levitsky */ 1707557d2bdcSMaxim Levitsky tmpkey = g_new0(uint8_t, luks->header.master_key_len); 1708557d2bdcSMaxim Levitsky } 1709557d2bdcSMaxim Levitsky 1710557d2bdcSMaxim Levitsky /* Erase an explicitly given keyslot */ 1711557d2bdcSMaxim Levitsky if (opts_luks->has_keyslot) { 1712557d2bdcSMaxim Levitsky int keyslot = opts_luks->keyslot; 1713557d2bdcSMaxim Levitsky 1714557d2bdcSMaxim Levitsky if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1715557d2bdcSMaxim Levitsky error_setg(errp, 1716557d2bdcSMaxim Levitsky "Invalid keyslot %i specified, must be between 0 and %i", 1717557d2bdcSMaxim Levitsky keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1718557d2bdcSMaxim Levitsky return -1; 1719557d2bdcSMaxim Levitsky } 1720557d2bdcSMaxim Levitsky 172116110c8bSMarkus Armbruster if (opts_luks->old_secret) { 1722557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1723557d2bdcSMaxim Levitsky keyslot, 1724557d2bdcSMaxim Levitsky old_password, 1725557d2bdcSMaxim Levitsky tmpkey, 1726557d2bdcSMaxim Levitsky readfunc, 1727557d2bdcSMaxim Levitsky opaque, 1728557d2bdcSMaxim Levitsky errp); 1729557d2bdcSMaxim Levitsky if (rv == -1) { 1730557d2bdcSMaxim Levitsky return -1; 1731557d2bdcSMaxim Levitsky } else if (rv == 0) { 1732557d2bdcSMaxim Levitsky error_setg(errp, 1733557d2bdcSMaxim Levitsky "Given keyslot %i doesn't contain the given " 1734557d2bdcSMaxim Levitsky "old password for erase operation", 1735557d2bdcSMaxim Levitsky keyslot); 1736557d2bdcSMaxim Levitsky return -1; 1737557d2bdcSMaxim Levitsky } 1738557d2bdcSMaxim Levitsky } 1739557d2bdcSMaxim Levitsky 1740557d2bdcSMaxim Levitsky if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { 1741557d2bdcSMaxim Levitsky error_setg(errp, 1742557d2bdcSMaxim Levitsky "Given keyslot %i is already erased (inactive) ", 1743557d2bdcSMaxim Levitsky keyslot); 1744557d2bdcSMaxim Levitsky return -1; 1745557d2bdcSMaxim Levitsky } 1746557d2bdcSMaxim Levitsky 1747557d2bdcSMaxim Levitsky if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { 1748557d2bdcSMaxim Levitsky error_setg(errp, 1749557d2bdcSMaxim Levitsky "Attempt to erase the only active keyslot %i " 1750557d2bdcSMaxim Levitsky "which will erase all the data in the image " 1751557d2bdcSMaxim Levitsky "irreversibly - refusing operation", 1752557d2bdcSMaxim Levitsky keyslot); 1753557d2bdcSMaxim Levitsky return -1; 1754557d2bdcSMaxim Levitsky } 1755557d2bdcSMaxim Levitsky 1756557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, keyslot, 1757557d2bdcSMaxim Levitsky writefunc, opaque, errp)) { 1758557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %i", keyslot); 1759557d2bdcSMaxim Levitsky return -1; 1760557d2bdcSMaxim Levitsky } 1761557d2bdcSMaxim Levitsky 1762557d2bdcSMaxim Levitsky /* Erase all keyslots that match the given old password */ 176316110c8bSMarkus Armbruster } else if (opts_luks->old_secret) { 1764557d2bdcSMaxim Levitsky 1765557d2bdcSMaxim Levitsky unsigned long slots_to_erase_bitmap = 0; 1766557d2bdcSMaxim Levitsky size_t i; 1767557d2bdcSMaxim Levitsky int slot_count; 1768557d2bdcSMaxim Levitsky 1769557d2bdcSMaxim Levitsky assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= 1770557d2bdcSMaxim Levitsky sizeof(slots_to_erase_bitmap) * 8); 1771557d2bdcSMaxim Levitsky 1772557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1773557d2bdcSMaxim Levitsky int rv = qcrypto_block_luks_load_key(block, 1774557d2bdcSMaxim Levitsky i, 1775557d2bdcSMaxim Levitsky old_password, 1776557d2bdcSMaxim Levitsky tmpkey, 1777557d2bdcSMaxim Levitsky readfunc, 1778557d2bdcSMaxim Levitsky opaque, 1779557d2bdcSMaxim Levitsky errp); 1780557d2bdcSMaxim Levitsky if (rv == -1) { 1781557d2bdcSMaxim Levitsky return -1; 1782557d2bdcSMaxim Levitsky } else if (rv == 1) { 1783557d2bdcSMaxim Levitsky bitmap_set(&slots_to_erase_bitmap, i, 1); 1784557d2bdcSMaxim Levitsky } 1785557d2bdcSMaxim Levitsky } 1786557d2bdcSMaxim Levitsky 1787557d2bdcSMaxim Levitsky slot_count = bitmap_count_one(&slots_to_erase_bitmap, 1788557d2bdcSMaxim Levitsky QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1789557d2bdcSMaxim Levitsky if (slot_count == 0) { 1790557d2bdcSMaxim Levitsky error_setg(errp, 1791557d2bdcSMaxim Levitsky "No keyslots match given (old) password for erase operation"); 1792557d2bdcSMaxim Levitsky return -1; 1793557d2bdcSMaxim Levitsky } 1794557d2bdcSMaxim Levitsky 1795557d2bdcSMaxim Levitsky if (!force && 1796557d2bdcSMaxim Levitsky slot_count == qcrypto_block_luks_count_active_slots(luks)) { 1797557d2bdcSMaxim Levitsky error_setg(errp, 1798557d2bdcSMaxim Levitsky "All the active keyslots match the (old) password that " 1799557d2bdcSMaxim Levitsky "was given and erasing them will erase all the data in " 1800557d2bdcSMaxim Levitsky "the image irreversibly - refusing operation"); 1801557d2bdcSMaxim Levitsky return -1; 1802557d2bdcSMaxim Levitsky } 1803557d2bdcSMaxim Levitsky 1804557d2bdcSMaxim Levitsky /* Now apply the update */ 1805557d2bdcSMaxim Levitsky for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1806557d2bdcSMaxim Levitsky if (!test_bit(i, &slots_to_erase_bitmap)) { 1807557d2bdcSMaxim Levitsky continue; 1808557d2bdcSMaxim Levitsky } 1809557d2bdcSMaxim Levitsky if (qcrypto_block_luks_erase_key(block, i, writefunc, 1810557d2bdcSMaxim Levitsky opaque, errp)) { 1811557d2bdcSMaxim Levitsky error_append_hint(errp, "Failed to erase keyslot %zu", i); 1812557d2bdcSMaxim Levitsky return -1; 1813557d2bdcSMaxim Levitsky } 1814557d2bdcSMaxim Levitsky } 1815557d2bdcSMaxim Levitsky } else { 1816557d2bdcSMaxim Levitsky error_setg(errp, 1817557d2bdcSMaxim Levitsky "To erase keyslot(s), either explicit keyslot index " 1818557d2bdcSMaxim Levitsky "or the password currently contained in them must be given"); 1819557d2bdcSMaxim Levitsky return -1; 1820557d2bdcSMaxim Levitsky } 1821557d2bdcSMaxim Levitsky return 0; 1822557d2bdcSMaxim Levitsky } 1823557d2bdcSMaxim Levitsky 1824557d2bdcSMaxim Levitsky static int 1825557d2bdcSMaxim Levitsky qcrypto_block_luks_amend_options(QCryptoBlock *block, 1826557d2bdcSMaxim Levitsky QCryptoBlockReadFunc readfunc, 1827557d2bdcSMaxim Levitsky QCryptoBlockWriteFunc writefunc, 1828557d2bdcSMaxim Levitsky void *opaque, 1829557d2bdcSMaxim Levitsky QCryptoBlockAmendOptions *options, 1830557d2bdcSMaxim Levitsky bool force, 1831557d2bdcSMaxim Levitsky Error **errp) 1832557d2bdcSMaxim Levitsky { 1833557d2bdcSMaxim Levitsky QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; 1834557d2bdcSMaxim Levitsky 1835557d2bdcSMaxim Levitsky switch (opts_luks->state) { 1836557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: 1837557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_add_keyslot(block, readfunc, 1838557d2bdcSMaxim Levitsky writefunc, opaque, 1839557d2bdcSMaxim Levitsky opts_luks, force, errp); 1840557d2bdcSMaxim Levitsky case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: 1841557d2bdcSMaxim Levitsky return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, 1842557d2bdcSMaxim Levitsky writefunc, opaque, 1843557d2bdcSMaxim Levitsky opts_luks, force, errp); 1844557d2bdcSMaxim Levitsky default: 1845557d2bdcSMaxim Levitsky g_assert_not_reached(); 1846557d2bdcSMaxim Levitsky } 1847557d2bdcSMaxim Levitsky } 18483e308f20SDaniel P. Berrange 184940c85028SDaniel P. Berrange static int qcrypto_block_luks_get_info(QCryptoBlock *block, 185040c85028SDaniel P. Berrange QCryptoBlockInfo *info, 185140c85028SDaniel P. Berrange Error **errp) 185240c85028SDaniel P. Berrange { 185340c85028SDaniel P. Berrange QCryptoBlockLUKS *luks = block->opaque; 185440c85028SDaniel P. Berrange QCryptoBlockInfoLUKSSlot *slot; 1855c3033fd3SEric Blake QCryptoBlockInfoLUKSSlotList **tail = &info->u.luks.slots; 185640c85028SDaniel P. Berrange size_t i; 185740c85028SDaniel P. Berrange 185840c85028SDaniel P. Berrange info->u.luks.cipher_alg = luks->cipher_alg; 185940c85028SDaniel P. Berrange info->u.luks.cipher_mode = luks->cipher_mode; 186040c85028SDaniel P. Berrange info->u.luks.ivgen_alg = luks->ivgen_alg; 186140c85028SDaniel P. Berrange if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) { 186240c85028SDaniel P. Berrange info->u.luks.has_ivgen_hash_alg = true; 186340c85028SDaniel P. Berrange info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg; 186440c85028SDaniel P. Berrange } 186540c85028SDaniel P. Berrange info->u.luks.hash_alg = luks->hash_alg; 186640c85028SDaniel P. Berrange info->u.luks.payload_offset = block->payload_offset; 186740c85028SDaniel P. Berrange info->u.luks.master_key_iters = luks->header.master_key_iterations; 186840c85028SDaniel P. Berrange info->u.luks.uuid = g_strndup((const char *)luks->header.uuid, 186940c85028SDaniel P. Berrange sizeof(luks->header.uuid)); 187040c85028SDaniel P. Berrange 187140c85028SDaniel P. Berrange for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1872c3033fd3SEric Blake slot = g_new0(QCryptoBlockInfoLUKSSlot, 1); 187340c85028SDaniel P. Berrange slot->active = luks->header.key_slots[i].active == 187440c85028SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1875f0d3c362SMaxim Levitsky slot->key_offset = luks->header.key_slots[i].key_offset_sector 187640c85028SDaniel P. Berrange * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; 187740c85028SDaniel P. Berrange if (slot->active) { 187840c85028SDaniel P. Berrange slot->has_iters = true; 187940c85028SDaniel P. Berrange slot->iters = luks->header.key_slots[i].iterations; 188040c85028SDaniel P. Berrange slot->has_stripes = true; 188140c85028SDaniel P. Berrange slot->stripes = luks->header.key_slots[i].stripes; 188240c85028SDaniel P. Berrange } 188340c85028SDaniel P. Berrange 1884c3033fd3SEric Blake QAPI_LIST_APPEND(tail, slot); 188540c85028SDaniel P. Berrange } 188640c85028SDaniel P. Berrange 188740c85028SDaniel P. Berrange return 0; 188840c85028SDaniel P. Berrange } 188940c85028SDaniel P. Berrange 189040c85028SDaniel P. Berrange 18913e308f20SDaniel P. Berrange static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 18923e308f20SDaniel P. Berrange { 1893557d2bdcSMaxim Levitsky QCryptoBlockLUKS *luks = block->opaque; 1894557d2bdcSMaxim Levitsky if (luks) { 1895557d2bdcSMaxim Levitsky g_free(luks->secret); 1896557d2bdcSMaxim Levitsky g_free(luks); 1897557d2bdcSMaxim Levitsky } 18983e308f20SDaniel P. Berrange } 18993e308f20SDaniel P. Berrange 19003e308f20SDaniel P. Berrange 19013e308f20SDaniel P. Berrange static int 19023e308f20SDaniel P. Berrange qcrypto_block_luks_decrypt(QCryptoBlock *block, 19034609742aSDaniel P. Berrange uint64_t offset, 19043e308f20SDaniel P. Berrange uint8_t *buf, 19053e308f20SDaniel P. Berrange size_t len, 19063e308f20SDaniel P. Berrange Error **errp) 19073e308f20SDaniel P. Berrange { 19084609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19094609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19100f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_decrypt_helper(block, 19113e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19124609742aSDaniel P. Berrange offset, buf, len, errp); 19133e308f20SDaniel P. Berrange } 19143e308f20SDaniel P. Berrange 19153e308f20SDaniel P. Berrange 19163e308f20SDaniel P. Berrange static int 19173e308f20SDaniel P. Berrange qcrypto_block_luks_encrypt(QCryptoBlock *block, 19184609742aSDaniel P. Berrange uint64_t offset, 19193e308f20SDaniel P. Berrange uint8_t *buf, 19203e308f20SDaniel P. Berrange size_t len, 19213e308f20SDaniel P. Berrange Error **errp) 19223e308f20SDaniel P. Berrange { 19234609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(offset, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19244609742aSDaniel P. Berrange assert(QEMU_IS_ALIGNED(len, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)); 19250f0d596cSVladimir Sementsov-Ogievskiy return qcrypto_block_encrypt_helper(block, 19263e308f20SDaniel P. Berrange QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 19274609742aSDaniel P. Berrange offset, buf, len, errp); 19283e308f20SDaniel P. Berrange } 19293e308f20SDaniel P. Berrange 19303e308f20SDaniel P. Berrange 19313e308f20SDaniel P. Berrange const QCryptoBlockDriver qcrypto_block_driver_luks = { 19323e308f20SDaniel P. Berrange .open = qcrypto_block_luks_open, 19333e308f20SDaniel P. Berrange .create = qcrypto_block_luks_create, 1934557d2bdcSMaxim Levitsky .amend = qcrypto_block_luks_amend_options, 193540c85028SDaniel P. Berrange .get_info = qcrypto_block_luks_get_info, 19363e308f20SDaniel P. Berrange .cleanup = qcrypto_block_luks_cleanup, 19373e308f20SDaniel P. Berrange .decrypt = qcrypto_block_luks_decrypt, 19383e308f20SDaniel P. Berrange .encrypt = qcrypto_block_luks_encrypt, 19393e308f20SDaniel P. Berrange .has_format = qcrypto_block_luks_has_format, 19403e308f20SDaniel P. Berrange }; 1941