qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qcrypto/luks: implement encryption key management

Next few patches will expose that functionality to the user.

Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20200608094030.670121-3-mlevitsk@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>

authored by

Maxim Levitsky and committed by
Max Reitz
557d2bdc 43cbd06d

+469 -6
+412 -4
crypto/block-luks.c
··· 32 32 #include "qemu/uuid.h" 33 33 34 34 #include "qemu/coroutine.h" 35 + #include "qemu/bitmap.h" 35 36 36 37 /* 37 38 * Reference for the LUKS format implemented here is ··· 69 70 #define QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED 0x00AC71F3 70 71 71 72 #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL 73 + 74 + #define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS 2000 75 + #define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40 72 76 73 77 static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = { 74 78 'L', 'U', 'K', 'S', 0xBA, 0xBE ··· 219 223 220 224 /* Hash algorithm used in pbkdf2 function */ 221 225 QCryptoHashAlgorithm hash_alg; 226 + 227 + /* Name of the secret that was used to open the image */ 228 + char *secret; 222 229 }; 223 230 224 231 ··· 720 727 Error **errp) 721 728 { 722 729 QCryptoBlockLUKS *luks = block->opaque; 723 - QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx]; 730 + QCryptoBlockLUKSKeySlot *slot; 724 731 g_autofree uint8_t *splitkey = NULL; 725 732 size_t splitkeylen; 726 733 g_autofree uint8_t *slotkey = NULL; ··· 730 737 uint64_t iters; 731 738 int ret = -1; 732 739 740 + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 741 + slot = &luks->header.key_slots[slot_idx]; 733 742 if (qcrypto_random_bytes(slot->salt, 734 743 QCRYPTO_BLOCK_LUKS_SALT_LEN, 735 744 errp) < 0) { ··· 890 899 Error **errp) 891 900 { 892 901 QCryptoBlockLUKS *luks = block->opaque; 893 - const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx]; 902 + const QCryptoBlockLUKSKeySlot *slot; 894 903 g_autofree uint8_t *splitkey = NULL; 895 904 size_t splitkeylen; 896 905 g_autofree uint8_t *possiblekey = NULL; ··· 900 909 g_autoptr(QCryptoIVGen) ivgen = NULL; 901 910 size_t niv; 902 911 912 + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 913 + slot = &luks->header.key_slots[slot_idx]; 903 914 if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) { 904 915 return 0; 905 916 } ··· 1069 1080 return -1; 1070 1081 } 1071 1082 1083 + /* 1084 + * Returns true if a slot i is marked as active 1085 + * (contains encrypted copy of the master key) 1086 + */ 1087 + static bool 1088 + qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks, 1089 + unsigned int slot_idx) 1090 + { 1091 + uint32_t val; 1092 + 1093 + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1094 + val = luks->header.key_slots[slot_idx].active; 1095 + return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED; 1096 + } 1097 + 1098 + /* 1099 + * Returns the number of slots that are marked as active 1100 + * (slots that contain encrypted copy of the master key) 1101 + */ 1102 + static unsigned int 1103 + qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks) 1104 + { 1105 + size_t i = 0; 1106 + unsigned int ret = 0; 1107 + 1108 + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1109 + if (qcrypto_block_luks_slot_active(luks, i)) { 1110 + ret++; 1111 + } 1112 + } 1113 + return ret; 1114 + } 1115 + 1116 + /* 1117 + * Finds first key slot which is not active 1118 + * Returns the key slot index, or -1 if it doesn't exist 1119 + */ 1120 + static int 1121 + qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks) 1122 + { 1123 + size_t i; 1124 + 1125 + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1126 + if (!qcrypto_block_luks_slot_active(luks, i)) { 1127 + return i; 1128 + } 1129 + } 1130 + return -1; 1131 + } 1132 + 1133 + /* 1134 + * Erases an keyslot given its index 1135 + * Returns: 1136 + * 0 if the keyslot was erased successfully 1137 + * -1 if a error occurred while erasing the keyslot 1138 + * 1139 + */ 1140 + static int 1141 + qcrypto_block_luks_erase_key(QCryptoBlock *block, 1142 + unsigned int slot_idx, 1143 + QCryptoBlockWriteFunc writefunc, 1144 + void *opaque, 1145 + Error **errp) 1146 + { 1147 + QCryptoBlockLUKS *luks = block->opaque; 1148 + QCryptoBlockLUKSKeySlot *slot; 1149 + g_autofree uint8_t *garbagesplitkey = NULL; 1150 + size_t splitkeylen; 1151 + size_t i; 1152 + Error *local_err = NULL; 1153 + int ret; 1154 + 1155 + assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1156 + slot = &luks->header.key_slots[slot_idx]; 1157 + 1158 + splitkeylen = luks->header.master_key_len * slot->stripes; 1159 + assert(splitkeylen > 0); 1160 + 1161 + garbagesplitkey = g_new0(uint8_t, splitkeylen); 1162 + 1163 + /* Reset the key slot header */ 1164 + memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN); 1165 + slot->iterations = 0; 1166 + slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED; 1167 + 1168 + ret = qcrypto_block_luks_store_header(block, writefunc, 1169 + opaque, &local_err); 1170 + 1171 + if (ret < 0) { 1172 + error_propagate(errp, local_err); 1173 + } 1174 + /* 1175 + * Now try to erase the key material, even if the header 1176 + * update failed 1177 + */ 1178 + for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) { 1179 + if (qcrypto_random_bytes(garbagesplitkey, 1180 + splitkeylen, &local_err) < 0) { 1181 + /* 1182 + * If we failed to get the random data, still write 1183 + * at least zeros to the key slot at least once 1184 + */ 1185 + error_propagate(errp, local_err); 1186 + 1187 + if (i > 0) { 1188 + return -1; 1189 + } 1190 + } 1191 + if (writefunc(block, 1192 + slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE, 1193 + garbagesplitkey, 1194 + splitkeylen, 1195 + opaque, 1196 + &local_err) != splitkeylen) { 1197 + error_propagate(errp, local_err); 1198 + return -1; 1199 + } 1200 + } 1201 + return ret; 1202 + } 1072 1203 1073 1204 static int 1074 1205 qcrypto_block_luks_open(QCryptoBlock *block, ··· 1099 1230 1100 1231 luks = g_new0(QCryptoBlockLUKS, 1); 1101 1232 block->opaque = luks; 1233 + luks->secret = g_strdup(options->u.luks.key_secret); 1102 1234 1103 1235 if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) { 1104 1236 goto fail; ··· 1164 1296 fail: 1165 1297 qcrypto_block_free_cipher(block); 1166 1298 qcrypto_ivgen_free(block->ivgen); 1299 + g_free(luks->secret); 1167 1300 g_free(luks); 1168 1301 return -1; 1169 1302 } ··· 1204 1337 1205 1338 memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); 1206 1339 if (!luks_opts.has_iter_time) { 1207 - luks_opts.iter_time = 2000; 1340 + luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1208 1341 } 1209 1342 if (!luks_opts.has_cipher_alg) { 1210 1343 luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; ··· 1244 1377 optprefix ? optprefix : ""); 1245 1378 goto error; 1246 1379 } 1380 + luks->secret = g_strdup(options->u.luks.key_secret); 1381 + 1247 1382 password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp); 1248 1383 if (!password) { 1249 1384 goto error; ··· 1471 1606 qcrypto_block_free_cipher(block); 1472 1607 qcrypto_ivgen_free(block->ivgen); 1473 1608 1609 + g_free(luks->secret); 1474 1610 g_free(luks); 1475 1611 return -1; 1476 1612 } 1477 1613 1614 + static int 1615 + qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block, 1616 + QCryptoBlockReadFunc readfunc, 1617 + QCryptoBlockWriteFunc writefunc, 1618 + void *opaque, 1619 + QCryptoBlockAmendOptionsLUKS *opts_luks, 1620 + bool force, 1621 + Error **errp) 1622 + { 1623 + QCryptoBlockLUKS *luks = block->opaque; 1624 + uint64_t iter_time = opts_luks->has_iter_time ? 1625 + opts_luks->iter_time : 1626 + QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; 1627 + int keyslot; 1628 + g_autofree char *old_password = NULL; 1629 + g_autofree char *new_password = NULL; 1630 + g_autofree uint8_t *master_key = NULL; 1631 + 1632 + char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret; 1633 + 1634 + if (!opts_luks->has_new_secret) { 1635 + error_setg(errp, "'new-secret' is required to activate a keyslot"); 1636 + return -1; 1637 + } 1638 + if (opts_luks->has_old_secret) { 1639 + error_setg(errp, 1640 + "'old-secret' must not be given when activating keyslots"); 1641 + return -1; 1642 + } 1643 + 1644 + if (opts_luks->has_keyslot) { 1645 + keyslot = opts_luks->keyslot; 1646 + if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1647 + error_setg(errp, 1648 + "Invalid keyslot %u specified, must be between 0 and %u", 1649 + keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1650 + return -1; 1651 + } 1652 + } else { 1653 + keyslot = qcrypto_block_luks_find_free_keyslot(luks); 1654 + if (keyslot == -1) { 1655 + error_setg(errp, 1656 + "Can't add a keyslot - all keyslots are in use"); 1657 + return -1; 1658 + } 1659 + } 1660 + 1661 + if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) { 1662 + error_setg(errp, 1663 + "Refusing to overwrite active keyslot %i - " 1664 + "please erase it first", 1665 + keyslot); 1666 + return -1; 1667 + } 1668 + 1669 + /* Locate the password that will be used to retrieve the master key */ 1670 + old_password = qcrypto_secret_lookup_as_utf8(secret, errp); 1671 + if (!old_password) { 1672 + return -1; 1673 + } 1674 + 1675 + /* Retrieve the master key */ 1676 + master_key = g_new0(uint8_t, luks->header.master_key_len); 1677 + 1678 + if (qcrypto_block_luks_find_key(block, old_password, master_key, 1679 + readfunc, opaque, errp) < 0) { 1680 + error_append_hint(errp, "Failed to retrieve the master key"); 1681 + return -1; 1682 + } 1683 + 1684 + /* Locate the new password*/ 1685 + new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp); 1686 + if (!new_password) { 1687 + return -1; 1688 + } 1689 + 1690 + /* Now set the new keyslots */ 1691 + if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key, 1692 + iter_time, writefunc, opaque, errp)) { 1693 + error_append_hint(errp, "Failed to write to keyslot %i", keyslot); 1694 + return -1; 1695 + } 1696 + return 0; 1697 + } 1698 + 1699 + static int 1700 + qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block, 1701 + QCryptoBlockReadFunc readfunc, 1702 + QCryptoBlockWriteFunc writefunc, 1703 + void *opaque, 1704 + QCryptoBlockAmendOptionsLUKS *opts_luks, 1705 + bool force, 1706 + Error **errp) 1707 + { 1708 + QCryptoBlockLUKS *luks = block->opaque; 1709 + g_autofree uint8_t *tmpkey = NULL; 1710 + g_autofree char *old_password = NULL; 1711 + 1712 + if (opts_luks->has_new_secret) { 1713 + error_setg(errp, 1714 + "'new-secret' must not be given when erasing keyslots"); 1715 + return -1; 1716 + } 1717 + if (opts_luks->has_iter_time) { 1718 + error_setg(errp, 1719 + "'iter-time' must not be given when erasing keyslots"); 1720 + return -1; 1721 + } 1722 + if (opts_luks->has_secret) { 1723 + error_setg(errp, 1724 + "'secret' must not be given when erasing keyslots"); 1725 + return -1; 1726 + } 1727 + 1728 + /* Load the old password if given */ 1729 + if (opts_luks->has_old_secret) { 1730 + old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret, 1731 + errp); 1732 + if (!old_password) { 1733 + return -1; 1734 + } 1735 + 1736 + /* 1737 + * Allocate a temporary key buffer that we will need when 1738 + * checking if slot matches the given old password 1739 + */ 1740 + tmpkey = g_new0(uint8_t, luks->header.master_key_len); 1741 + } 1742 + 1743 + /* Erase an explicitly given keyslot */ 1744 + if (opts_luks->has_keyslot) { 1745 + int keyslot = opts_luks->keyslot; 1746 + 1747 + if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) { 1748 + error_setg(errp, 1749 + "Invalid keyslot %i specified, must be between 0 and %i", 1750 + keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1); 1751 + return -1; 1752 + } 1753 + 1754 + if (opts_luks->has_old_secret) { 1755 + int rv = qcrypto_block_luks_load_key(block, 1756 + keyslot, 1757 + old_password, 1758 + tmpkey, 1759 + readfunc, 1760 + opaque, 1761 + errp); 1762 + if (rv == -1) { 1763 + return -1; 1764 + } else if (rv == 0) { 1765 + error_setg(errp, 1766 + "Given keyslot %i doesn't contain the given " 1767 + "old password for erase operation", 1768 + keyslot); 1769 + return -1; 1770 + } 1771 + } 1772 + 1773 + if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) { 1774 + error_setg(errp, 1775 + "Given keyslot %i is already erased (inactive) ", 1776 + keyslot); 1777 + return -1; 1778 + } 1779 + 1780 + if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) { 1781 + error_setg(errp, 1782 + "Attempt to erase the only active keyslot %i " 1783 + "which will erase all the data in the image " 1784 + "irreversibly - refusing operation", 1785 + keyslot); 1786 + return -1; 1787 + } 1788 + 1789 + if (qcrypto_block_luks_erase_key(block, keyslot, 1790 + writefunc, opaque, errp)) { 1791 + error_append_hint(errp, "Failed to erase keyslot %i", keyslot); 1792 + return -1; 1793 + } 1794 + 1795 + /* Erase all keyslots that match the given old password */ 1796 + } else if (opts_luks->has_old_secret) { 1797 + 1798 + unsigned long slots_to_erase_bitmap = 0; 1799 + size_t i; 1800 + int slot_count; 1801 + 1802 + assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <= 1803 + sizeof(slots_to_erase_bitmap) * 8); 1804 + 1805 + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1806 + int rv = qcrypto_block_luks_load_key(block, 1807 + i, 1808 + old_password, 1809 + tmpkey, 1810 + readfunc, 1811 + opaque, 1812 + errp); 1813 + if (rv == -1) { 1814 + return -1; 1815 + } else if (rv == 1) { 1816 + bitmap_set(&slots_to_erase_bitmap, i, 1); 1817 + } 1818 + } 1819 + 1820 + slot_count = bitmap_count_one(&slots_to_erase_bitmap, 1821 + QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS); 1822 + if (slot_count == 0) { 1823 + error_setg(errp, 1824 + "No keyslots match given (old) password for erase operation"); 1825 + return -1; 1826 + } 1827 + 1828 + if (!force && 1829 + slot_count == qcrypto_block_luks_count_active_slots(luks)) { 1830 + error_setg(errp, 1831 + "All the active keyslots match the (old) password that " 1832 + "was given and erasing them will erase all the data in " 1833 + "the image irreversibly - refusing operation"); 1834 + return -1; 1835 + } 1836 + 1837 + /* Now apply the update */ 1838 + for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) { 1839 + if (!test_bit(i, &slots_to_erase_bitmap)) { 1840 + continue; 1841 + } 1842 + if (qcrypto_block_luks_erase_key(block, i, writefunc, 1843 + opaque, errp)) { 1844 + error_append_hint(errp, "Failed to erase keyslot %zu", i); 1845 + return -1; 1846 + } 1847 + } 1848 + } else { 1849 + error_setg(errp, 1850 + "To erase keyslot(s), either explicit keyslot index " 1851 + "or the password currently contained in them must be given"); 1852 + return -1; 1853 + } 1854 + return 0; 1855 + } 1856 + 1857 + static int 1858 + qcrypto_block_luks_amend_options(QCryptoBlock *block, 1859 + QCryptoBlockReadFunc readfunc, 1860 + QCryptoBlockWriteFunc writefunc, 1861 + void *opaque, 1862 + QCryptoBlockAmendOptions *options, 1863 + bool force, 1864 + Error **errp) 1865 + { 1866 + QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks; 1867 + 1868 + switch (opts_luks->state) { 1869 + case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE: 1870 + return qcrypto_block_luks_amend_add_keyslot(block, readfunc, 1871 + writefunc, opaque, 1872 + opts_luks, force, errp); 1873 + case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE: 1874 + return qcrypto_block_luks_amend_erase_keyslots(block, readfunc, 1875 + writefunc, opaque, 1876 + opts_luks, force, errp); 1877 + default: 1878 + g_assert_not_reached(); 1879 + } 1880 + } 1478 1881 1479 1882 static int qcrypto_block_luks_get_info(QCryptoBlock *block, 1480 1883 QCryptoBlockInfo *info, ··· 1523 1926 1524 1927 static void qcrypto_block_luks_cleanup(QCryptoBlock *block) 1525 1928 { 1526 - g_free(block->opaque); 1929 + QCryptoBlockLUKS *luks = block->opaque; 1930 + if (luks) { 1931 + g_free(luks->secret); 1932 + g_free(luks); 1933 + } 1527 1934 } 1528 1935 1529 1936 ··· 1560 1967 const QCryptoBlockDriver qcrypto_block_driver_luks = { 1561 1968 .open = qcrypto_block_luks_open, 1562 1969 .create = qcrypto_block_luks_create, 1970 + .amend = qcrypto_block_luks_amend_options, 1563 1971 .get_info = qcrypto_block_luks_get_info, 1564 1972 .cleanup = qcrypto_block_luks_cleanup, 1565 1973 .decrypt = qcrypto_block_luks_decrypt,
+57 -2
qapi/crypto.json
··· 297 297 'uuid': 'str', 298 298 'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }} 299 299 300 - 301 300 ## 302 301 # @QCryptoBlockInfo: 303 302 # ··· 310 309 'discriminator': 'format', 311 310 'data': { 'luks': 'QCryptoBlockInfoLUKS' } } 312 311 312 + ## 313 + # @QCryptoBlockLUKSKeyslotState: 314 + # 315 + # Defines state of keyslots that are affected by the update 316 + # 317 + # @active: The slots contain the given password and marked as active 318 + # @inactive: The slots are erased (contain garbage) and marked as inactive 319 + # 320 + # Since: 5.1 321 + ## 322 + { 'enum': 'QCryptoBlockLUKSKeyslotState', 323 + 'data': [ 'active', 'inactive' ] } 313 324 314 325 315 326 ## 327 + # @QCryptoBlockAmendOptionsLUKS: 328 + # 329 + # This struct defines the update parameters that activate/de-activate set 330 + # of keyslots 331 + # 332 + # @state: the desired state of the keyslots 333 + # 334 + # @new-secret: The ID of a QCryptoSecret object providing the password to be 335 + # written into added active keyslots 336 + # 337 + # @old-secret: Optional (for deactivation only) 338 + # If given will deactive all keyslots that 339 + # match password located in QCryptoSecret with this ID 340 + # 341 + # @iter-time: Optional (for activation only) 342 + # Number of milliseconds to spend in 343 + # PBKDF passphrase processing for the newly activated keyslot. 344 + # Currently defaults to 2000. 345 + # 346 + # @keyslot: Optional. ID of the keyslot to activate/deactivate. 347 + # For keyslot activation, keyslot should not be active already 348 + # (this is unsafe to update an active keyslot), 349 + # but possible if 'force' parameter is given. 350 + # If keyslot is not given, first free keyslot will be written. 351 + # 352 + # For keyslot deactivation, this parameter specifies the exact 353 + # keyslot to deactivate 354 + # 355 + # @secret: Optional. The ID of a QCryptoSecret object providing the 356 + # password to use to retrive current master key. 357 + # Defaults to the same secret that was used to open the image 358 + # 359 + # 360 + # Since 5.1 361 + ## 362 + { 'struct': 'QCryptoBlockAmendOptionsLUKS', 363 + 'data': { 'state': 'QCryptoBlockLUKSKeyslotState', 364 + '*new-secret': 'str', 365 + '*old-secret': 'str', 366 + '*keyslot': 'int', 367 + '*iter-time': 'int', 368 + '*secret': 'str' } } 369 + 370 + ## 316 371 # @QCryptoBlockAmendOptions: 317 372 # 318 373 # The options that are available for all encryption formats ··· 324 379 'base': 'QCryptoBlockOptionsBase', 325 380 'discriminator': 'format', 326 381 'data': { 327 - } } 382 + 'luks': 'QCryptoBlockAmendOptionsLUKS' } }