11c6fdbd8SKent Overstreet // SPDX-License-Identifier: GPL-2.0 21c6fdbd8SKent Overstreet #include "bcachefs.h" 31c6fdbd8SKent Overstreet #include "checksum.h" 41c6fdbd8SKent Overstreet #include "super.h" 51c6fdbd8SKent Overstreet #include "super-io.h" 61c6fdbd8SKent Overstreet 71c6fdbd8SKent Overstreet #include <linux/crc32c.h> 81c6fdbd8SKent Overstreet #include <linux/crypto.h> 941e63382Sjpsollie #include <linux/xxhash.h> 101c6fdbd8SKent Overstreet #include <linux/key.h> 111c6fdbd8SKent Overstreet #include <linux/random.h> 121c6fdbd8SKent Overstreet #include <linux/scatterlist.h> 131c6fdbd8SKent Overstreet #include <crypto/algapi.h> 141c6fdbd8SKent Overstreet #include <crypto/chacha.h> 151c6fdbd8SKent Overstreet #include <crypto/hash.h> 161c6fdbd8SKent Overstreet #include <crypto/poly1305.h> 171c6fdbd8SKent Overstreet #include <crypto/skcipher.h> 181c6fdbd8SKent Overstreet #include <keys/user-type.h> 191c6fdbd8SKent Overstreet 2080ff5d18Sjpsollie /* 2180ff5d18Sjpsollie * bch2_checksum state is an abstraction of the checksum state calculated over different pages. 2280ff5d18Sjpsollie * it features page merging without having the checksum algorithm lose its state. 2380ff5d18Sjpsollie * for native checksum aglorithms (like crc), a default seed value will do. 2480ff5d18Sjpsollie * for hash-like algorithms, a state needs to be stored 2580ff5d18Sjpsollie */ 2680ff5d18Sjpsollie 2780ff5d18Sjpsollie struct bch2_checksum_state { 2880ff5d18Sjpsollie union { 2980ff5d18Sjpsollie u64 seed; 3041e63382Sjpsollie struct xxh64_state h64state; 3180ff5d18Sjpsollie }; 3280ff5d18Sjpsollie unsigned int type; 3380ff5d18Sjpsollie }; 3480ff5d18Sjpsollie 3580ff5d18Sjpsollie static void bch2_checksum_init(struct bch2_checksum_state *state) 361c6fdbd8SKent Overstreet { 3780ff5d18Sjpsollie switch (state->type) { 38*6404dcc9SKent Overstreet case BCH_CSUM_none: 39*6404dcc9SKent Overstreet case BCH_CSUM_crc32c: 40*6404dcc9SKent Overstreet case BCH_CSUM_crc64: 4180ff5d18Sjpsollie state->seed = 0; 4280ff5d18Sjpsollie break; 43*6404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 4480ff5d18Sjpsollie state->seed = U32_MAX; 4580ff5d18Sjpsollie break; 46*6404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 4780ff5d18Sjpsollie state->seed = U64_MAX; 4880ff5d18Sjpsollie break; 49*6404dcc9SKent Overstreet case BCH_CSUM_xxhash: 5041e63382Sjpsollie xxh64_reset(&state->h64state, 0); 5141e63382Sjpsollie break; 521c6fdbd8SKent Overstreet default: 531c6fdbd8SKent Overstreet BUG(); 541c6fdbd8SKent Overstreet } 551c6fdbd8SKent Overstreet } 561c6fdbd8SKent Overstreet 5780ff5d18Sjpsollie static u64 bch2_checksum_final(const struct bch2_checksum_state *state) 581c6fdbd8SKent Overstreet { 5980ff5d18Sjpsollie switch (state->type) { 60*6404dcc9SKent Overstreet case BCH_CSUM_none: 61*6404dcc9SKent Overstreet case BCH_CSUM_crc32c: 62*6404dcc9SKent Overstreet case BCH_CSUM_crc64: 6380ff5d18Sjpsollie return state->seed; 64*6404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 6580ff5d18Sjpsollie return state->seed ^ U32_MAX; 66*6404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 6780ff5d18Sjpsollie return state->seed ^ U64_MAX; 68*6404dcc9SKent Overstreet case BCH_CSUM_xxhash: 6941e63382Sjpsollie return xxh64_digest(&state->h64state); 701c6fdbd8SKent Overstreet default: 711c6fdbd8SKent Overstreet BUG(); 721c6fdbd8SKent Overstreet } 731c6fdbd8SKent Overstreet } 741c6fdbd8SKent Overstreet 7580ff5d18Sjpsollie static void bch2_checksum_update(struct bch2_checksum_state *state, const void *data, size_t len) 761c6fdbd8SKent Overstreet { 7780ff5d18Sjpsollie switch (state->type) { 78*6404dcc9SKent Overstreet case BCH_CSUM_none: 7980ff5d18Sjpsollie return; 80*6404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 81*6404dcc9SKent Overstreet case BCH_CSUM_crc32c: 8280ff5d18Sjpsollie state->seed = crc32c(state->seed, data, len); 8380ff5d18Sjpsollie break; 84*6404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 85*6404dcc9SKent Overstreet case BCH_CSUM_crc64: 8680ff5d18Sjpsollie state->seed = crc64_be(state->seed, data, len); 8780ff5d18Sjpsollie break; 88*6404dcc9SKent Overstreet case BCH_CSUM_xxhash: 8941e63382Sjpsollie xxh64_update(&state->h64state, data, len); 9041e63382Sjpsollie break; 911c6fdbd8SKent Overstreet default: 921c6fdbd8SKent Overstreet BUG(); 931c6fdbd8SKent Overstreet } 941c6fdbd8SKent Overstreet } 951c6fdbd8SKent Overstreet 961c6fdbd8SKent Overstreet static inline void do_encrypt_sg(struct crypto_sync_skcipher *tfm, 971c6fdbd8SKent Overstreet struct nonce nonce, 981c6fdbd8SKent Overstreet struct scatterlist *sg, size_t len) 991c6fdbd8SKent Overstreet { 1001c6fdbd8SKent Overstreet SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 1011c6fdbd8SKent Overstreet int ret; 1021c6fdbd8SKent Overstreet 1031c6fdbd8SKent Overstreet skcipher_request_set_sync_tfm(req, tfm); 1041c6fdbd8SKent Overstreet skcipher_request_set_crypt(req, sg, sg, len, nonce.d); 1051c6fdbd8SKent Overstreet 1061c6fdbd8SKent Overstreet ret = crypto_skcipher_encrypt(req); 1071c6fdbd8SKent Overstreet BUG_ON(ret); 1081c6fdbd8SKent Overstreet } 1091c6fdbd8SKent Overstreet 1101c6fdbd8SKent Overstreet static inline void do_encrypt(struct crypto_sync_skcipher *tfm, 1111c6fdbd8SKent Overstreet struct nonce nonce, 1121c6fdbd8SKent Overstreet void *buf, size_t len) 1131c6fdbd8SKent Overstreet { 1141c6fdbd8SKent Overstreet struct scatterlist sg; 1151c6fdbd8SKent Overstreet 1161c6fdbd8SKent Overstreet sg_init_one(&sg, buf, len); 1171c6fdbd8SKent Overstreet do_encrypt_sg(tfm, nonce, &sg, len); 1181c6fdbd8SKent Overstreet } 1191c6fdbd8SKent Overstreet 1201c6fdbd8SKent Overstreet int bch2_chacha_encrypt_key(struct bch_key *key, struct nonce nonce, 1211c6fdbd8SKent Overstreet void *buf, size_t len) 1221c6fdbd8SKent Overstreet { 1231c6fdbd8SKent Overstreet struct crypto_sync_skcipher *chacha20 = 1241c6fdbd8SKent Overstreet crypto_alloc_sync_skcipher("chacha20", 0, 0); 1251c6fdbd8SKent Overstreet int ret; 1261c6fdbd8SKent Overstreet 1271c6fdbd8SKent Overstreet if (!chacha20) { 1281c6fdbd8SKent Overstreet pr_err("error requesting chacha20 module: %li", PTR_ERR(chacha20)); 1291c6fdbd8SKent Overstreet return PTR_ERR(chacha20); 1301c6fdbd8SKent Overstreet } 1311c6fdbd8SKent Overstreet 1321c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&chacha20->base, 1331c6fdbd8SKent Overstreet (void *) key, sizeof(*key)); 1341c6fdbd8SKent Overstreet if (ret) { 1351c6fdbd8SKent Overstreet pr_err("crypto_skcipher_setkey() error: %i", ret); 1361c6fdbd8SKent Overstreet goto err; 1371c6fdbd8SKent Overstreet } 1381c6fdbd8SKent Overstreet 1391c6fdbd8SKent Overstreet do_encrypt(chacha20, nonce, buf, len); 1401c6fdbd8SKent Overstreet err: 1411c6fdbd8SKent Overstreet crypto_free_sync_skcipher(chacha20); 1421c6fdbd8SKent Overstreet return ret; 1431c6fdbd8SKent Overstreet } 1441c6fdbd8SKent Overstreet 1451c6fdbd8SKent Overstreet static void gen_poly_key(struct bch_fs *c, struct shash_desc *desc, 1461c6fdbd8SKent Overstreet struct nonce nonce) 1471c6fdbd8SKent Overstreet { 1481c6fdbd8SKent Overstreet u8 key[POLY1305_KEY_SIZE]; 1491c6fdbd8SKent Overstreet 1501c6fdbd8SKent Overstreet nonce.d[3] ^= BCH_NONCE_POLY; 1511c6fdbd8SKent Overstreet 1521c6fdbd8SKent Overstreet memset(key, 0, sizeof(key)); 1531c6fdbd8SKent Overstreet do_encrypt(c->chacha20, nonce, key, sizeof(key)); 1541c6fdbd8SKent Overstreet 1551c6fdbd8SKent Overstreet desc->tfm = c->poly1305; 1561c6fdbd8SKent Overstreet crypto_shash_init(desc); 1571c6fdbd8SKent Overstreet crypto_shash_update(desc, key, sizeof(key)); 1581c6fdbd8SKent Overstreet } 1591c6fdbd8SKent Overstreet 1601c6fdbd8SKent Overstreet struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type, 1611c6fdbd8SKent Overstreet struct nonce nonce, const void *data, size_t len) 1621c6fdbd8SKent Overstreet { 1631c6fdbd8SKent Overstreet switch (type) { 164*6404dcc9SKent Overstreet case BCH_CSUM_none: 165*6404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 166*6404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 167*6404dcc9SKent Overstreet case BCH_CSUM_crc32c: 168*6404dcc9SKent Overstreet case BCH_CSUM_xxhash: 169*6404dcc9SKent Overstreet case BCH_CSUM_crc64: { 17080ff5d18Sjpsollie struct bch2_checksum_state state; 1711c6fdbd8SKent Overstreet 17280ff5d18Sjpsollie state.type = type; 1731c6fdbd8SKent Overstreet 17480ff5d18Sjpsollie bch2_checksum_init(&state); 17580ff5d18Sjpsollie bch2_checksum_update(&state, data, len); 17680ff5d18Sjpsollie 17780ff5d18Sjpsollie return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; 1781c6fdbd8SKent Overstreet } 1791c6fdbd8SKent Overstreet 180*6404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_80: 181*6404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_128: { 1821c6fdbd8SKent Overstreet SHASH_DESC_ON_STACK(desc, c->poly1305); 1831c6fdbd8SKent Overstreet u8 digest[POLY1305_DIGEST_SIZE]; 1841c6fdbd8SKent Overstreet struct bch_csum ret = { 0 }; 1851c6fdbd8SKent Overstreet 1861c6fdbd8SKent Overstreet gen_poly_key(c, desc, nonce); 1871c6fdbd8SKent Overstreet 1881c6fdbd8SKent Overstreet crypto_shash_update(desc, data, len); 1891c6fdbd8SKent Overstreet crypto_shash_final(desc, digest); 1901c6fdbd8SKent Overstreet 1911c6fdbd8SKent Overstreet memcpy(&ret, digest, bch_crc_bytes[type]); 1921c6fdbd8SKent Overstreet return ret; 1931c6fdbd8SKent Overstreet } 1941c6fdbd8SKent Overstreet default: 1951c6fdbd8SKent Overstreet BUG(); 1961c6fdbd8SKent Overstreet } 1971c6fdbd8SKent Overstreet } 1981c6fdbd8SKent Overstreet 1991c6fdbd8SKent Overstreet void bch2_encrypt(struct bch_fs *c, unsigned type, 2001c6fdbd8SKent Overstreet struct nonce nonce, void *data, size_t len) 2011c6fdbd8SKent Overstreet { 2021c6fdbd8SKent Overstreet if (!bch2_csum_type_is_encryption(type)) 2031c6fdbd8SKent Overstreet return; 2041c6fdbd8SKent Overstreet 2051c6fdbd8SKent Overstreet do_encrypt(c->chacha20, nonce, data, len); 2061c6fdbd8SKent Overstreet } 2071c6fdbd8SKent Overstreet 2081c6fdbd8SKent Overstreet static struct bch_csum __bch2_checksum_bio(struct bch_fs *c, unsigned type, 2091c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio, 2101c6fdbd8SKent Overstreet struct bvec_iter *iter) 2111c6fdbd8SKent Overstreet { 2121c6fdbd8SKent Overstreet struct bio_vec bv; 2131c6fdbd8SKent Overstreet 2141c6fdbd8SKent Overstreet switch (type) { 215*6404dcc9SKent Overstreet case BCH_CSUM_none: 2161c6fdbd8SKent Overstreet return (struct bch_csum) { 0 }; 217*6404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 218*6404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 219*6404dcc9SKent Overstreet case BCH_CSUM_crc32c: 220*6404dcc9SKent Overstreet case BCH_CSUM_xxhash: 221*6404dcc9SKent Overstreet case BCH_CSUM_crc64: { 22280ff5d18Sjpsollie struct bch2_checksum_state state; 22380ff5d18Sjpsollie 22480ff5d18Sjpsollie state.type = type; 22580ff5d18Sjpsollie bch2_checksum_init(&state); 2261c6fdbd8SKent Overstreet 2271c6fdbd8SKent Overstreet #ifdef CONFIG_HIGHMEM 2281c6fdbd8SKent Overstreet __bio_for_each_segment(bv, bio, *iter, *iter) { 2291c6fdbd8SKent Overstreet void *p = kmap_atomic(bv.bv_page) + bv.bv_offset; 23080ff5d18Sjpsollie bch2_checksum_update(&state, p, bv.bv_len); 2311c6fdbd8SKent Overstreet kunmap_atomic(p); 2321c6fdbd8SKent Overstreet } 2331c6fdbd8SKent Overstreet #else 2340fd7263eSKent Overstreet __bio_for_each_bvec(bv, bio, *iter, *iter) 23580ff5d18Sjpsollie bch2_checksum_update(&state, page_address(bv.bv_page) + bv.bv_offset, 2361c6fdbd8SKent Overstreet bv.bv_len); 2371c6fdbd8SKent Overstreet #endif 23880ff5d18Sjpsollie return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; 2391c6fdbd8SKent Overstreet } 2401c6fdbd8SKent Overstreet 241*6404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_80: 242*6404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_128: { 2431c6fdbd8SKent Overstreet SHASH_DESC_ON_STACK(desc, c->poly1305); 2441c6fdbd8SKent Overstreet u8 digest[POLY1305_DIGEST_SIZE]; 2451c6fdbd8SKent Overstreet struct bch_csum ret = { 0 }; 2461c6fdbd8SKent Overstreet 2471c6fdbd8SKent Overstreet gen_poly_key(c, desc, nonce); 2481c6fdbd8SKent Overstreet 2491c6fdbd8SKent Overstreet #ifdef CONFIG_HIGHMEM 2501c6fdbd8SKent Overstreet __bio_for_each_segment(bv, bio, *iter, *iter) { 2511c6fdbd8SKent Overstreet void *p = kmap_atomic(bv.bv_page) + bv.bv_offset; 2521c6fdbd8SKent Overstreet 2531c6fdbd8SKent Overstreet crypto_shash_update(desc, p, bv.bv_len); 2541c6fdbd8SKent Overstreet kunmap_atomic(p); 2551c6fdbd8SKent Overstreet } 2561c6fdbd8SKent Overstreet #else 2570fd7263eSKent Overstreet __bio_for_each_bvec(bv, bio, *iter, *iter) 2581c6fdbd8SKent Overstreet crypto_shash_update(desc, 2591c6fdbd8SKent Overstreet page_address(bv.bv_page) + bv.bv_offset, 2601c6fdbd8SKent Overstreet bv.bv_len); 2611c6fdbd8SKent Overstreet #endif 2621c6fdbd8SKent Overstreet crypto_shash_final(desc, digest); 2631c6fdbd8SKent Overstreet 2641c6fdbd8SKent Overstreet memcpy(&ret, digest, bch_crc_bytes[type]); 2651c6fdbd8SKent Overstreet return ret; 2661c6fdbd8SKent Overstreet } 2671c6fdbd8SKent Overstreet default: 2681c6fdbd8SKent Overstreet BUG(); 2691c6fdbd8SKent Overstreet } 2701c6fdbd8SKent Overstreet } 2711c6fdbd8SKent Overstreet 2721c6fdbd8SKent Overstreet struct bch_csum bch2_checksum_bio(struct bch_fs *c, unsigned type, 2731c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio) 2741c6fdbd8SKent Overstreet { 2751c6fdbd8SKent Overstreet struct bvec_iter iter = bio->bi_iter; 2761c6fdbd8SKent Overstreet 2771c6fdbd8SKent Overstreet return __bch2_checksum_bio(c, type, nonce, bio, &iter); 2781c6fdbd8SKent Overstreet } 2791c6fdbd8SKent Overstreet 2801c6fdbd8SKent Overstreet void bch2_encrypt_bio(struct bch_fs *c, unsigned type, 2811c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio) 2821c6fdbd8SKent Overstreet { 2831c6fdbd8SKent Overstreet struct bio_vec bv; 2841c6fdbd8SKent Overstreet struct bvec_iter iter; 2851c6fdbd8SKent Overstreet struct scatterlist sgl[16], *sg = sgl; 2861c6fdbd8SKent Overstreet size_t bytes = 0; 2871c6fdbd8SKent Overstreet 2881c6fdbd8SKent Overstreet if (!bch2_csum_type_is_encryption(type)) 2891c6fdbd8SKent Overstreet return; 2901c6fdbd8SKent Overstreet 2911c6fdbd8SKent Overstreet sg_init_table(sgl, ARRAY_SIZE(sgl)); 2921c6fdbd8SKent Overstreet 2931c6fdbd8SKent Overstreet bio_for_each_segment(bv, bio, iter) { 2941c6fdbd8SKent Overstreet if (sg == sgl + ARRAY_SIZE(sgl)) { 2951c6fdbd8SKent Overstreet sg_mark_end(sg - 1); 2961c6fdbd8SKent Overstreet do_encrypt_sg(c->chacha20, nonce, sgl, bytes); 2971c6fdbd8SKent Overstreet 2981c6fdbd8SKent Overstreet nonce = nonce_add(nonce, bytes); 2991c6fdbd8SKent Overstreet bytes = 0; 3001c6fdbd8SKent Overstreet 3011c6fdbd8SKent Overstreet sg_init_table(sgl, ARRAY_SIZE(sgl)); 3021c6fdbd8SKent Overstreet sg = sgl; 3031c6fdbd8SKent Overstreet } 3041c6fdbd8SKent Overstreet 3051c6fdbd8SKent Overstreet sg_set_page(sg++, bv.bv_page, bv.bv_len, bv.bv_offset); 3061c6fdbd8SKent Overstreet bytes += bv.bv_len; 3071c6fdbd8SKent Overstreet } 3081c6fdbd8SKent Overstreet 3091c6fdbd8SKent Overstreet sg_mark_end(sg - 1); 3101c6fdbd8SKent Overstreet do_encrypt_sg(c->chacha20, nonce, sgl, bytes); 3111c6fdbd8SKent Overstreet } 3121c6fdbd8SKent Overstreet 3136009b4e5SKent Overstreet struct bch_csum bch2_checksum_merge(unsigned type, struct bch_csum a, 3141c6fdbd8SKent Overstreet struct bch_csum b, size_t b_len) 3151c6fdbd8SKent Overstreet { 31680ff5d18Sjpsollie struct bch2_checksum_state state; 31780ff5d18Sjpsollie 31880ff5d18Sjpsollie state.type = type; 31980ff5d18Sjpsollie bch2_checksum_init(&state); 32080ff5d18Sjpsollie state.seed = a.lo; 32180ff5d18Sjpsollie 3221c6fdbd8SKent Overstreet BUG_ON(!bch2_checksum_mergeable(type)); 3231c6fdbd8SKent Overstreet 3241c6fdbd8SKent Overstreet while (b_len) { 3251c6fdbd8SKent Overstreet unsigned b = min_t(unsigned, b_len, PAGE_SIZE); 3261c6fdbd8SKent Overstreet 32780ff5d18Sjpsollie bch2_checksum_update(&state, 3281c6fdbd8SKent Overstreet page_address(ZERO_PAGE(0)), b); 3291c6fdbd8SKent Overstreet b_len -= b; 3301c6fdbd8SKent Overstreet } 33180ff5d18Sjpsollie a.lo = bch2_checksum_final(&state); 3321c6fdbd8SKent Overstreet a.lo ^= b.lo; 3331c6fdbd8SKent Overstreet a.hi ^= b.hi; 3341c6fdbd8SKent Overstreet return a; 3351c6fdbd8SKent Overstreet } 3361c6fdbd8SKent Overstreet 3371c6fdbd8SKent Overstreet int bch2_rechecksum_bio(struct bch_fs *c, struct bio *bio, 3381c6fdbd8SKent Overstreet struct bversion version, 3391c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked crc_old, 3401c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc_a, 3411c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc_b, 3421c6fdbd8SKent Overstreet unsigned len_a, unsigned len_b, 3431c6fdbd8SKent Overstreet unsigned new_csum_type) 3441c6fdbd8SKent Overstreet { 3451c6fdbd8SKent Overstreet struct bvec_iter iter = bio->bi_iter; 3461c6fdbd8SKent Overstreet struct nonce nonce = extent_nonce(version, crc_old); 3471c6fdbd8SKent Overstreet struct bch_csum merged = { 0 }; 3481c6fdbd8SKent Overstreet struct crc_split { 3491c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc; 3501c6fdbd8SKent Overstreet unsigned len; 3511c6fdbd8SKent Overstreet unsigned csum_type; 3521c6fdbd8SKent Overstreet struct bch_csum csum; 3531c6fdbd8SKent Overstreet } splits[3] = { 3541c6fdbd8SKent Overstreet { crc_a, len_a, new_csum_type }, 3551c6fdbd8SKent Overstreet { crc_b, len_b, new_csum_type }, 3561c6fdbd8SKent Overstreet { NULL, bio_sectors(bio) - len_a - len_b, new_csum_type }, 3571c6fdbd8SKent Overstreet }, *i; 3581c6fdbd8SKent Overstreet bool mergeable = crc_old.csum_type == new_csum_type && 3591c6fdbd8SKent Overstreet bch2_checksum_mergeable(new_csum_type); 3601c6fdbd8SKent Overstreet unsigned crc_nonce = crc_old.nonce; 3611c6fdbd8SKent Overstreet 3621c6fdbd8SKent Overstreet BUG_ON(len_a + len_b > bio_sectors(bio)); 3631c6fdbd8SKent Overstreet BUG_ON(crc_old.uncompressed_size != bio_sectors(bio)); 364ab05de4cSKent Overstreet BUG_ON(crc_is_compressed(crc_old)); 3651c6fdbd8SKent Overstreet BUG_ON(bch2_csum_type_is_encryption(crc_old.csum_type) != 3661c6fdbd8SKent Overstreet bch2_csum_type_is_encryption(new_csum_type)); 3671c6fdbd8SKent Overstreet 3681c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) { 3691c6fdbd8SKent Overstreet iter.bi_size = i->len << 9; 3701c6fdbd8SKent Overstreet if (mergeable || i->crc) 3711c6fdbd8SKent Overstreet i->csum = __bch2_checksum_bio(c, i->csum_type, 3721c6fdbd8SKent Overstreet nonce, bio, &iter); 3731c6fdbd8SKent Overstreet else 3741c6fdbd8SKent Overstreet bio_advance_iter(bio, &iter, i->len << 9); 3751c6fdbd8SKent Overstreet nonce = nonce_add(nonce, i->len << 9); 3761c6fdbd8SKent Overstreet } 3771c6fdbd8SKent Overstreet 3781c6fdbd8SKent Overstreet if (mergeable) 3791c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) 3801c6fdbd8SKent Overstreet merged = bch2_checksum_merge(new_csum_type, merged, 3811c6fdbd8SKent Overstreet i->csum, i->len << 9); 3821c6fdbd8SKent Overstreet else 3831c6fdbd8SKent Overstreet merged = bch2_checksum_bio(c, crc_old.csum_type, 3841c6fdbd8SKent Overstreet extent_nonce(version, crc_old), bio); 3851c6fdbd8SKent Overstreet 3861c6fdbd8SKent Overstreet if (bch2_crc_cmp(merged, crc_old.csum)) 3871c6fdbd8SKent Overstreet return -EIO; 3881c6fdbd8SKent Overstreet 3891c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) { 3901c6fdbd8SKent Overstreet if (i->crc) 3911c6fdbd8SKent Overstreet *i->crc = (struct bch_extent_crc_unpacked) { 3921c6fdbd8SKent Overstreet .csum_type = i->csum_type, 393ab05de4cSKent Overstreet .compression_type = crc_old.compression_type, 3941c6fdbd8SKent Overstreet .compressed_size = i->len, 3951c6fdbd8SKent Overstreet .uncompressed_size = i->len, 3961c6fdbd8SKent Overstreet .offset = 0, 3971c6fdbd8SKent Overstreet .live_size = i->len, 3981c6fdbd8SKent Overstreet .nonce = crc_nonce, 3991c6fdbd8SKent Overstreet .csum = i->csum, 4001c6fdbd8SKent Overstreet }; 4011c6fdbd8SKent Overstreet 4021c6fdbd8SKent Overstreet if (bch2_csum_type_is_encryption(new_csum_type)) 4031c6fdbd8SKent Overstreet crc_nonce += i->len; 4041c6fdbd8SKent Overstreet } 4051c6fdbd8SKent Overstreet 4061c6fdbd8SKent Overstreet return 0; 4071c6fdbd8SKent Overstreet } 4081c6fdbd8SKent Overstreet 4091c6fdbd8SKent Overstreet #ifdef __KERNEL__ 4101c6fdbd8SKent Overstreet int bch2_request_key(struct bch_sb *sb, struct bch_key *key) 4111c6fdbd8SKent Overstreet { 4121c6fdbd8SKent Overstreet char key_description[60]; 4131c6fdbd8SKent Overstreet struct key *keyring_key; 4141c6fdbd8SKent Overstreet const struct user_key_payload *ukp; 4151c6fdbd8SKent Overstreet int ret; 4161c6fdbd8SKent Overstreet 4171c6fdbd8SKent Overstreet snprintf(key_description, sizeof(key_description), 4181c6fdbd8SKent Overstreet "bcachefs:%pUb", &sb->user_uuid); 4191c6fdbd8SKent Overstreet 4201c6fdbd8SKent Overstreet keyring_key = request_key(&key_type_logon, key_description, NULL); 4211c6fdbd8SKent Overstreet if (IS_ERR(keyring_key)) 4221c6fdbd8SKent Overstreet return PTR_ERR(keyring_key); 4231c6fdbd8SKent Overstreet 4241c6fdbd8SKent Overstreet down_read(&keyring_key->sem); 4251c6fdbd8SKent Overstreet ukp = dereference_key_locked(keyring_key); 4261c6fdbd8SKent Overstreet if (ukp->datalen == sizeof(*key)) { 4271c6fdbd8SKent Overstreet memcpy(key, ukp->data, ukp->datalen); 4281c6fdbd8SKent Overstreet ret = 0; 4291c6fdbd8SKent Overstreet } else { 4301c6fdbd8SKent Overstreet ret = -EINVAL; 4311c6fdbd8SKent Overstreet } 4321c6fdbd8SKent Overstreet up_read(&keyring_key->sem); 4331c6fdbd8SKent Overstreet key_put(keyring_key); 4341c6fdbd8SKent Overstreet 4351c6fdbd8SKent Overstreet return ret; 4361c6fdbd8SKent Overstreet } 4371c6fdbd8SKent Overstreet #else 4381c6fdbd8SKent Overstreet #include <keyutils.h> 4391c6fdbd8SKent Overstreet #include <uuid/uuid.h> 4401c6fdbd8SKent Overstreet 4411c6fdbd8SKent Overstreet int bch2_request_key(struct bch_sb *sb, struct bch_key *key) 4421c6fdbd8SKent Overstreet { 4431c6fdbd8SKent Overstreet key_serial_t key_id; 4441c6fdbd8SKent Overstreet char key_description[60]; 4451c6fdbd8SKent Overstreet char uuid[40]; 4461c6fdbd8SKent Overstreet 4471c6fdbd8SKent Overstreet uuid_unparse_lower(sb->user_uuid.b, uuid); 4481c6fdbd8SKent Overstreet sprintf(key_description, "bcachefs:%s", uuid); 4491c6fdbd8SKent Overstreet 4501c6fdbd8SKent Overstreet key_id = request_key("user", key_description, NULL, 4511c6fdbd8SKent Overstreet KEY_SPEC_USER_KEYRING); 4521c6fdbd8SKent Overstreet if (key_id < 0) 4531c6fdbd8SKent Overstreet return -errno; 4541c6fdbd8SKent Overstreet 4551c6fdbd8SKent Overstreet if (keyctl_read(key_id, (void *) key, sizeof(*key)) != sizeof(*key)) 4561c6fdbd8SKent Overstreet return -1; 4571c6fdbd8SKent Overstreet 4581c6fdbd8SKent Overstreet return 0; 4591c6fdbd8SKent Overstreet } 4601c6fdbd8SKent Overstreet #endif 4611c6fdbd8SKent Overstreet 4621c6fdbd8SKent Overstreet int bch2_decrypt_sb_key(struct bch_fs *c, 4631c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt, 4641c6fdbd8SKent Overstreet struct bch_key *key) 4651c6fdbd8SKent Overstreet { 4661c6fdbd8SKent Overstreet struct bch_encrypted_key sb_key = crypt->key; 4671c6fdbd8SKent Overstreet struct bch_key user_key; 4681c6fdbd8SKent Overstreet int ret = 0; 4691c6fdbd8SKent Overstreet 4701c6fdbd8SKent Overstreet /* is key encrypted? */ 4711c6fdbd8SKent Overstreet if (!bch2_key_is_encrypted(&sb_key)) 4721c6fdbd8SKent Overstreet goto out; 4731c6fdbd8SKent Overstreet 4741c6fdbd8SKent Overstreet ret = bch2_request_key(c->disk_sb.sb, &user_key); 4751c6fdbd8SKent Overstreet if (ret) { 4761c6fdbd8SKent Overstreet bch_err(c, "error requesting encryption key: %i", ret); 4771c6fdbd8SKent Overstreet goto err; 4781c6fdbd8SKent Overstreet } 4791c6fdbd8SKent Overstreet 4801c6fdbd8SKent Overstreet /* decrypt real key: */ 4811c6fdbd8SKent Overstreet ret = bch2_chacha_encrypt_key(&user_key, bch2_sb_key_nonce(c), 4821c6fdbd8SKent Overstreet &sb_key, sizeof(sb_key)); 4831c6fdbd8SKent Overstreet if (ret) 4841c6fdbd8SKent Overstreet goto err; 4851c6fdbd8SKent Overstreet 4861c6fdbd8SKent Overstreet if (bch2_key_is_encrypted(&sb_key)) { 4871c6fdbd8SKent Overstreet bch_err(c, "incorrect encryption key"); 4881c6fdbd8SKent Overstreet ret = -EINVAL; 4891c6fdbd8SKent Overstreet goto err; 4901c6fdbd8SKent Overstreet } 4911c6fdbd8SKent Overstreet out: 4921c6fdbd8SKent Overstreet *key = sb_key.key; 4931c6fdbd8SKent Overstreet err: 4941c6fdbd8SKent Overstreet memzero_explicit(&sb_key, sizeof(sb_key)); 4951c6fdbd8SKent Overstreet memzero_explicit(&user_key, sizeof(user_key)); 4961c6fdbd8SKent Overstreet return ret; 4971c6fdbd8SKent Overstreet } 4981c6fdbd8SKent Overstreet 4991c6fdbd8SKent Overstreet static int bch2_alloc_ciphers(struct bch_fs *c) 5001c6fdbd8SKent Overstreet { 5011c6fdbd8SKent Overstreet if (!c->chacha20) 5021c6fdbd8SKent Overstreet c->chacha20 = crypto_alloc_sync_skcipher("chacha20", 0, 0); 5031c6fdbd8SKent Overstreet if (IS_ERR(c->chacha20)) { 5041c6fdbd8SKent Overstreet bch_err(c, "error requesting chacha20 module: %li", 5051c6fdbd8SKent Overstreet PTR_ERR(c->chacha20)); 5061c6fdbd8SKent Overstreet return PTR_ERR(c->chacha20); 5071c6fdbd8SKent Overstreet } 5081c6fdbd8SKent Overstreet 5091c6fdbd8SKent Overstreet if (!c->poly1305) 5101c6fdbd8SKent Overstreet c->poly1305 = crypto_alloc_shash("poly1305", 0, 0); 5111c6fdbd8SKent Overstreet if (IS_ERR(c->poly1305)) { 5121c6fdbd8SKent Overstreet bch_err(c, "error requesting poly1305 module: %li", 5131c6fdbd8SKent Overstreet PTR_ERR(c->poly1305)); 5141c6fdbd8SKent Overstreet return PTR_ERR(c->poly1305); 5151c6fdbd8SKent Overstreet } 5161c6fdbd8SKent Overstreet 5171c6fdbd8SKent Overstreet return 0; 5181c6fdbd8SKent Overstreet } 5191c6fdbd8SKent Overstreet 5201c6fdbd8SKent Overstreet int bch2_disable_encryption(struct bch_fs *c) 5211c6fdbd8SKent Overstreet { 5221c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 5231c6fdbd8SKent Overstreet struct bch_key key; 5241c6fdbd8SKent Overstreet int ret = -EINVAL; 5251c6fdbd8SKent Overstreet 5261c6fdbd8SKent Overstreet mutex_lock(&c->sb_lock); 5271c6fdbd8SKent Overstreet 5281c6fdbd8SKent Overstreet crypt = bch2_sb_get_crypt(c->disk_sb.sb); 5291c6fdbd8SKent Overstreet if (!crypt) 5301c6fdbd8SKent Overstreet goto out; 5311c6fdbd8SKent Overstreet 5321c6fdbd8SKent Overstreet /* is key encrypted? */ 5331c6fdbd8SKent Overstreet ret = 0; 5341c6fdbd8SKent Overstreet if (bch2_key_is_encrypted(&crypt->key)) 5351c6fdbd8SKent Overstreet goto out; 5361c6fdbd8SKent Overstreet 5371c6fdbd8SKent Overstreet ret = bch2_decrypt_sb_key(c, crypt, &key); 5381c6fdbd8SKent Overstreet if (ret) 5391c6fdbd8SKent Overstreet goto out; 5401c6fdbd8SKent Overstreet 5411c6fdbd8SKent Overstreet crypt->key.magic = BCH_KEY_MAGIC; 5421c6fdbd8SKent Overstreet crypt->key.key = key; 5431c6fdbd8SKent Overstreet 5441c6fdbd8SKent Overstreet SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 0); 5451c6fdbd8SKent Overstreet bch2_write_super(c); 5461c6fdbd8SKent Overstreet out: 5471c6fdbd8SKent Overstreet mutex_unlock(&c->sb_lock); 5481c6fdbd8SKent Overstreet 5491c6fdbd8SKent Overstreet return ret; 5501c6fdbd8SKent Overstreet } 5511c6fdbd8SKent Overstreet 5521c6fdbd8SKent Overstreet int bch2_enable_encryption(struct bch_fs *c, bool keyed) 5531c6fdbd8SKent Overstreet { 5541c6fdbd8SKent Overstreet struct bch_encrypted_key key; 5551c6fdbd8SKent Overstreet struct bch_key user_key; 5561c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 5571c6fdbd8SKent Overstreet int ret = -EINVAL; 5581c6fdbd8SKent Overstreet 5591c6fdbd8SKent Overstreet mutex_lock(&c->sb_lock); 5601c6fdbd8SKent Overstreet 5611c6fdbd8SKent Overstreet /* Do we already have an encryption key? */ 5621c6fdbd8SKent Overstreet if (bch2_sb_get_crypt(c->disk_sb.sb)) 5631c6fdbd8SKent Overstreet goto err; 5641c6fdbd8SKent Overstreet 5651c6fdbd8SKent Overstreet ret = bch2_alloc_ciphers(c); 5661c6fdbd8SKent Overstreet if (ret) 5671c6fdbd8SKent Overstreet goto err; 5681c6fdbd8SKent Overstreet 5691c6fdbd8SKent Overstreet key.magic = BCH_KEY_MAGIC; 5701c6fdbd8SKent Overstreet get_random_bytes(&key.key, sizeof(key.key)); 5711c6fdbd8SKent Overstreet 5721c6fdbd8SKent Overstreet if (keyed) { 5731c6fdbd8SKent Overstreet ret = bch2_request_key(c->disk_sb.sb, &user_key); 5741c6fdbd8SKent Overstreet if (ret) { 5751c6fdbd8SKent Overstreet bch_err(c, "error requesting encryption key: %i", ret); 5761c6fdbd8SKent Overstreet goto err; 5771c6fdbd8SKent Overstreet } 5781c6fdbd8SKent Overstreet 5791c6fdbd8SKent Overstreet ret = bch2_chacha_encrypt_key(&user_key, bch2_sb_key_nonce(c), 5801c6fdbd8SKent Overstreet &key, sizeof(key)); 5811c6fdbd8SKent Overstreet if (ret) 5821c6fdbd8SKent Overstreet goto err; 5831c6fdbd8SKent Overstreet } 5841c6fdbd8SKent Overstreet 5851c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&c->chacha20->base, 5861c6fdbd8SKent Overstreet (void *) &key.key, sizeof(key.key)); 5871c6fdbd8SKent Overstreet if (ret) 5881c6fdbd8SKent Overstreet goto err; 5891c6fdbd8SKent Overstreet 5901c6fdbd8SKent Overstreet crypt = bch2_sb_resize_crypt(&c->disk_sb, sizeof(*crypt) / sizeof(u64)); 5911c6fdbd8SKent Overstreet if (!crypt) { 5921c6fdbd8SKent Overstreet ret = -ENOMEM; /* XXX this technically could be -ENOSPC */ 5931c6fdbd8SKent Overstreet goto err; 5941c6fdbd8SKent Overstreet } 5951c6fdbd8SKent Overstreet 5961c6fdbd8SKent Overstreet crypt->key = key; 5971c6fdbd8SKent Overstreet 5981c6fdbd8SKent Overstreet /* write superblock */ 5991c6fdbd8SKent Overstreet SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 1); 6001c6fdbd8SKent Overstreet bch2_write_super(c); 6011c6fdbd8SKent Overstreet err: 6021c6fdbd8SKent Overstreet mutex_unlock(&c->sb_lock); 6031c6fdbd8SKent Overstreet memzero_explicit(&user_key, sizeof(user_key)); 6041c6fdbd8SKent Overstreet memzero_explicit(&key, sizeof(key)); 6051c6fdbd8SKent Overstreet return ret; 6061c6fdbd8SKent Overstreet } 6071c6fdbd8SKent Overstreet 6081c6fdbd8SKent Overstreet void bch2_fs_encryption_exit(struct bch_fs *c) 6091c6fdbd8SKent Overstreet { 6101c6fdbd8SKent Overstreet if (!IS_ERR_OR_NULL(c->poly1305)) 6111c6fdbd8SKent Overstreet crypto_free_shash(c->poly1305); 6121c6fdbd8SKent Overstreet if (!IS_ERR_OR_NULL(c->chacha20)) 6131c6fdbd8SKent Overstreet crypto_free_sync_skcipher(c->chacha20); 6141c6fdbd8SKent Overstreet if (!IS_ERR_OR_NULL(c->sha256)) 6151c6fdbd8SKent Overstreet crypto_free_shash(c->sha256); 6161c6fdbd8SKent Overstreet } 6171c6fdbd8SKent Overstreet 6181c6fdbd8SKent Overstreet int bch2_fs_encryption_init(struct bch_fs *c) 6191c6fdbd8SKent Overstreet { 6201c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 6211c6fdbd8SKent Overstreet struct bch_key key; 6221c6fdbd8SKent Overstreet int ret = 0; 6231c6fdbd8SKent Overstreet 6241c6fdbd8SKent Overstreet pr_verbose_init(c->opts, ""); 6251c6fdbd8SKent Overstreet 6261c6fdbd8SKent Overstreet c->sha256 = crypto_alloc_shash("sha256", 0, 0); 6271c6fdbd8SKent Overstreet if (IS_ERR(c->sha256)) { 6281c6fdbd8SKent Overstreet bch_err(c, "error requesting sha256 module"); 6291c6fdbd8SKent Overstreet ret = PTR_ERR(c->sha256); 6301c6fdbd8SKent Overstreet goto out; 6311c6fdbd8SKent Overstreet } 6321c6fdbd8SKent Overstreet 6331c6fdbd8SKent Overstreet crypt = bch2_sb_get_crypt(c->disk_sb.sb); 6341c6fdbd8SKent Overstreet if (!crypt) 6351c6fdbd8SKent Overstreet goto out; 6361c6fdbd8SKent Overstreet 6371c6fdbd8SKent Overstreet ret = bch2_alloc_ciphers(c); 6381c6fdbd8SKent Overstreet if (ret) 6391c6fdbd8SKent Overstreet goto out; 6401c6fdbd8SKent Overstreet 6411c6fdbd8SKent Overstreet ret = bch2_decrypt_sb_key(c, crypt, &key); 6421c6fdbd8SKent Overstreet if (ret) 6431c6fdbd8SKent Overstreet goto out; 6441c6fdbd8SKent Overstreet 6451c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&c->chacha20->base, 6461c6fdbd8SKent Overstreet (void *) &key.key, sizeof(key.key)); 6471c6fdbd8SKent Overstreet if (ret) 6481c6fdbd8SKent Overstreet goto out; 6491c6fdbd8SKent Overstreet out: 6501c6fdbd8SKent Overstreet memzero_explicit(&key, sizeof(key)); 6511c6fdbd8SKent Overstreet pr_verbose_init(c->opts, "ret %i", ret); 6521c6fdbd8SKent Overstreet return ret; 6531c6fdbd8SKent Overstreet } 654