11c6fdbd8SKent Overstreet // SPDX-License-Identifier: GPL-2.0 21c6fdbd8SKent Overstreet #include "bcachefs.h" 31c6fdbd8SKent Overstreet #include "checksum.h" 4d4bf5eecSKent Overstreet #include "errcode.h" 51c6fdbd8SKent Overstreet #include "super.h" 61c6fdbd8SKent Overstreet #include "super-io.h" 71c6fdbd8SKent Overstreet 81c6fdbd8SKent Overstreet #include <linux/crc32c.h> 91c6fdbd8SKent Overstreet #include <linux/crypto.h> 1041e63382Sjpsollie #include <linux/xxhash.h> 111c6fdbd8SKent Overstreet #include <linux/key.h> 121c6fdbd8SKent Overstreet #include <linux/random.h> 131c6fdbd8SKent Overstreet #include <linux/scatterlist.h> 141c6fdbd8SKent Overstreet #include <crypto/algapi.h> 151c6fdbd8SKent Overstreet #include <crypto/chacha.h> 161c6fdbd8SKent Overstreet #include <crypto/hash.h> 171c6fdbd8SKent Overstreet #include <crypto/poly1305.h> 181c6fdbd8SKent Overstreet #include <crypto/skcipher.h> 191c6fdbd8SKent Overstreet #include <keys/user-type.h> 201c6fdbd8SKent Overstreet 2180ff5d18Sjpsollie /* 2280ff5d18Sjpsollie * bch2_checksum state is an abstraction of the checksum state calculated over different pages. 2380ff5d18Sjpsollie * it features page merging without having the checksum algorithm lose its state. 2480ff5d18Sjpsollie * for native checksum aglorithms (like crc), a default seed value will do. 2580ff5d18Sjpsollie * for hash-like algorithms, a state needs to be stored 2680ff5d18Sjpsollie */ 2780ff5d18Sjpsollie 2880ff5d18Sjpsollie struct bch2_checksum_state { 2980ff5d18Sjpsollie union { 3080ff5d18Sjpsollie u64 seed; 3141e63382Sjpsollie struct xxh64_state h64state; 3280ff5d18Sjpsollie }; 3380ff5d18Sjpsollie unsigned int type; 3480ff5d18Sjpsollie }; 3580ff5d18Sjpsollie 3680ff5d18Sjpsollie static void bch2_checksum_init(struct bch2_checksum_state *state) 371c6fdbd8SKent Overstreet { 3880ff5d18Sjpsollie switch (state->type) { 396404dcc9SKent Overstreet case BCH_CSUM_none: 406404dcc9SKent Overstreet case BCH_CSUM_crc32c: 416404dcc9SKent Overstreet case BCH_CSUM_crc64: 4280ff5d18Sjpsollie state->seed = 0; 4380ff5d18Sjpsollie break; 446404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 4580ff5d18Sjpsollie state->seed = U32_MAX; 4680ff5d18Sjpsollie break; 476404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 4880ff5d18Sjpsollie state->seed = U64_MAX; 4980ff5d18Sjpsollie break; 506404dcc9SKent Overstreet case BCH_CSUM_xxhash: 5141e63382Sjpsollie xxh64_reset(&state->h64state, 0); 5241e63382Sjpsollie break; 531c6fdbd8SKent Overstreet default: 541c6fdbd8SKent Overstreet BUG(); 551c6fdbd8SKent Overstreet } 561c6fdbd8SKent Overstreet } 571c6fdbd8SKent Overstreet 5880ff5d18Sjpsollie static u64 bch2_checksum_final(const struct bch2_checksum_state *state) 591c6fdbd8SKent Overstreet { 6080ff5d18Sjpsollie switch (state->type) { 616404dcc9SKent Overstreet case BCH_CSUM_none: 626404dcc9SKent Overstreet case BCH_CSUM_crc32c: 636404dcc9SKent Overstreet case BCH_CSUM_crc64: 6480ff5d18Sjpsollie return state->seed; 656404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 6680ff5d18Sjpsollie return state->seed ^ U32_MAX; 676404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 6880ff5d18Sjpsollie return state->seed ^ U64_MAX; 696404dcc9SKent Overstreet case BCH_CSUM_xxhash: 7041e63382Sjpsollie return xxh64_digest(&state->h64state); 711c6fdbd8SKent Overstreet default: 721c6fdbd8SKent Overstreet BUG(); 731c6fdbd8SKent Overstreet } 741c6fdbd8SKent Overstreet } 751c6fdbd8SKent Overstreet 7680ff5d18Sjpsollie static void bch2_checksum_update(struct bch2_checksum_state *state, const void *data, size_t len) 771c6fdbd8SKent Overstreet { 7880ff5d18Sjpsollie switch (state->type) { 796404dcc9SKent Overstreet case BCH_CSUM_none: 8080ff5d18Sjpsollie return; 816404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 826404dcc9SKent Overstreet case BCH_CSUM_crc32c: 8380ff5d18Sjpsollie state->seed = crc32c(state->seed, data, len); 8480ff5d18Sjpsollie break; 856404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 866404dcc9SKent Overstreet case BCH_CSUM_crc64: 8780ff5d18Sjpsollie state->seed = crc64_be(state->seed, data, len); 8880ff5d18Sjpsollie break; 896404dcc9SKent Overstreet case BCH_CSUM_xxhash: 9041e63382Sjpsollie xxh64_update(&state->h64state, data, len); 9141e63382Sjpsollie break; 921c6fdbd8SKent Overstreet default: 931c6fdbd8SKent Overstreet BUG(); 941c6fdbd8SKent Overstreet } 951c6fdbd8SKent Overstreet } 961c6fdbd8SKent Overstreet 97a9de137bSKent Overstreet static inline int do_encrypt_sg(struct crypto_sync_skcipher *tfm, 981c6fdbd8SKent Overstreet struct nonce nonce, 991c6fdbd8SKent Overstreet struct scatterlist *sg, size_t len) 1001c6fdbd8SKent Overstreet { 1011c6fdbd8SKent Overstreet SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 1021c6fdbd8SKent Overstreet int ret; 1031c6fdbd8SKent Overstreet 1041c6fdbd8SKent Overstreet skcipher_request_set_sync_tfm(req, tfm); 1051c6fdbd8SKent Overstreet skcipher_request_set_crypt(req, sg, sg, len, nonce.d); 1061c6fdbd8SKent Overstreet 1071c6fdbd8SKent Overstreet ret = crypto_skcipher_encrypt(req); 108a9de137bSKent Overstreet if (ret) 109a9de137bSKent Overstreet pr_err("got error %i from crypto_skcipher_encrypt()", ret); 110a9de137bSKent Overstreet 111a9de137bSKent Overstreet return ret; 1121c6fdbd8SKent Overstreet } 1131c6fdbd8SKent Overstreet 114a9de137bSKent Overstreet static inline int do_encrypt(struct crypto_sync_skcipher *tfm, 1151c6fdbd8SKent Overstreet struct nonce nonce, 1161c6fdbd8SKent Overstreet void *buf, size_t len) 1171c6fdbd8SKent Overstreet { 118636d4eefSKent Overstreet if (!is_vmalloc_addr(buf)) { 1191c6fdbd8SKent Overstreet struct scatterlist sg; 1201c6fdbd8SKent Overstreet 121c346def9SKent Overstreet sg_init_table(&sg, 1); 122c346def9SKent Overstreet sg_set_page(&sg, 123c346def9SKent Overstreet is_vmalloc_addr(buf) 124c346def9SKent Overstreet ? vmalloc_to_page(buf) 125c346def9SKent Overstreet : virt_to_page(buf), 126c346def9SKent Overstreet len, offset_in_page(buf)); 127a9de137bSKent Overstreet return do_encrypt_sg(tfm, nonce, &sg, len); 128636d4eefSKent Overstreet } else { 129636d4eefSKent Overstreet unsigned pages = buf_pages(buf, len); 130636d4eefSKent Overstreet struct scatterlist *sg; 131636d4eefSKent Overstreet size_t orig_len = len; 132636d4eefSKent Overstreet int ret, i; 133636d4eefSKent Overstreet 1343e3e02e6SKent Overstreet sg = kmalloc_array(pages, sizeof(*sg), GFP_KERNEL); 135636d4eefSKent Overstreet if (!sg) 13665d48e35SKent Overstreet return -BCH_ERR_ENOMEM_do_encrypt; 137636d4eefSKent Overstreet 138636d4eefSKent Overstreet sg_init_table(sg, pages); 139636d4eefSKent Overstreet 140636d4eefSKent Overstreet for (i = 0; i < pages; i++) { 141636d4eefSKent Overstreet unsigned offset = offset_in_page(buf); 142636d4eefSKent Overstreet unsigned pg_len = min(len, PAGE_SIZE - offset); 143636d4eefSKent Overstreet 144636d4eefSKent Overstreet sg_set_page(sg + i, vmalloc_to_page(buf), pg_len, offset); 145636d4eefSKent Overstreet buf += pg_len; 146636d4eefSKent Overstreet len -= pg_len; 147636d4eefSKent Overstreet } 148636d4eefSKent Overstreet 149636d4eefSKent Overstreet ret = do_encrypt_sg(tfm, nonce, sg, orig_len); 150636d4eefSKent Overstreet kfree(sg); 151636d4eefSKent Overstreet return ret; 152636d4eefSKent Overstreet } 1531c6fdbd8SKent Overstreet } 1541c6fdbd8SKent Overstreet 1551c6fdbd8SKent Overstreet int bch2_chacha_encrypt_key(struct bch_key *key, struct nonce nonce, 1561c6fdbd8SKent Overstreet void *buf, size_t len) 1571c6fdbd8SKent Overstreet { 1581c6fdbd8SKent Overstreet struct crypto_sync_skcipher *chacha20 = 1591c6fdbd8SKent Overstreet crypto_alloc_sync_skcipher("chacha20", 0, 0); 1601c6fdbd8SKent Overstreet int ret; 1611c6fdbd8SKent Overstreet 1621c6fdbd8SKent Overstreet if (!chacha20) { 1631c6fdbd8SKent Overstreet pr_err("error requesting chacha20 module: %li", PTR_ERR(chacha20)); 1641c6fdbd8SKent Overstreet return PTR_ERR(chacha20); 1651c6fdbd8SKent Overstreet } 1661c6fdbd8SKent Overstreet 1671c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&chacha20->base, 1681c6fdbd8SKent Overstreet (void *) key, sizeof(*key)); 1691c6fdbd8SKent Overstreet if (ret) { 1701c6fdbd8SKent Overstreet pr_err("crypto_skcipher_setkey() error: %i", ret); 1711c6fdbd8SKent Overstreet goto err; 1721c6fdbd8SKent Overstreet } 1731c6fdbd8SKent Overstreet 174a9de137bSKent Overstreet ret = do_encrypt(chacha20, nonce, buf, len); 1751c6fdbd8SKent Overstreet err: 1761c6fdbd8SKent Overstreet crypto_free_sync_skcipher(chacha20); 1771c6fdbd8SKent Overstreet return ret; 1781c6fdbd8SKent Overstreet } 1791c6fdbd8SKent Overstreet 180a9de137bSKent Overstreet static int gen_poly_key(struct bch_fs *c, struct shash_desc *desc, 1811c6fdbd8SKent Overstreet struct nonce nonce) 1821c6fdbd8SKent Overstreet { 1831c6fdbd8SKent Overstreet u8 key[POLY1305_KEY_SIZE]; 184a9de137bSKent Overstreet int ret; 1851c6fdbd8SKent Overstreet 1861c6fdbd8SKent Overstreet nonce.d[3] ^= BCH_NONCE_POLY; 1871c6fdbd8SKent Overstreet 1881c6fdbd8SKent Overstreet memset(key, 0, sizeof(key)); 189a9de137bSKent Overstreet ret = do_encrypt(c->chacha20, nonce, key, sizeof(key)); 190a9de137bSKent Overstreet if (ret) 191a9de137bSKent Overstreet return ret; 1921c6fdbd8SKent Overstreet 1931c6fdbd8SKent Overstreet desc->tfm = c->poly1305; 1941c6fdbd8SKent Overstreet crypto_shash_init(desc); 1951c6fdbd8SKent Overstreet crypto_shash_update(desc, key, sizeof(key)); 196a9de137bSKent Overstreet return 0; 1971c6fdbd8SKent Overstreet } 1981c6fdbd8SKent Overstreet 1991c6fdbd8SKent Overstreet struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type, 2001c6fdbd8SKent Overstreet struct nonce nonce, const void *data, size_t len) 2011c6fdbd8SKent Overstreet { 2021c6fdbd8SKent Overstreet switch (type) { 2036404dcc9SKent Overstreet case BCH_CSUM_none: 2046404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 2056404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 2066404dcc9SKent Overstreet case BCH_CSUM_crc32c: 2076404dcc9SKent Overstreet case BCH_CSUM_xxhash: 2086404dcc9SKent Overstreet case BCH_CSUM_crc64: { 20980ff5d18Sjpsollie struct bch2_checksum_state state; 2101c6fdbd8SKent Overstreet 21180ff5d18Sjpsollie state.type = type; 2121c6fdbd8SKent Overstreet 21380ff5d18Sjpsollie bch2_checksum_init(&state); 21480ff5d18Sjpsollie bch2_checksum_update(&state, data, len); 21580ff5d18Sjpsollie 21680ff5d18Sjpsollie return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; 2171c6fdbd8SKent Overstreet } 2181c6fdbd8SKent Overstreet 2196404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_80: 2206404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_128: { 2211c6fdbd8SKent Overstreet SHASH_DESC_ON_STACK(desc, c->poly1305); 2221c6fdbd8SKent Overstreet u8 digest[POLY1305_DIGEST_SIZE]; 2231c6fdbd8SKent Overstreet struct bch_csum ret = { 0 }; 2241c6fdbd8SKent Overstreet 2251c6fdbd8SKent Overstreet gen_poly_key(c, desc, nonce); 2261c6fdbd8SKent Overstreet 2271c6fdbd8SKent Overstreet crypto_shash_update(desc, data, len); 2281c6fdbd8SKent Overstreet crypto_shash_final(desc, digest); 2291c6fdbd8SKent Overstreet 2301c6fdbd8SKent Overstreet memcpy(&ret, digest, bch_crc_bytes[type]); 2311c6fdbd8SKent Overstreet return ret; 2321c6fdbd8SKent Overstreet } 2331c6fdbd8SKent Overstreet default: 2341c6fdbd8SKent Overstreet BUG(); 2351c6fdbd8SKent Overstreet } 2361c6fdbd8SKent Overstreet } 2371c6fdbd8SKent Overstreet 238a9de137bSKent Overstreet int bch2_encrypt(struct bch_fs *c, unsigned type, 2391c6fdbd8SKent Overstreet struct nonce nonce, void *data, size_t len) 2401c6fdbd8SKent Overstreet { 2411c6fdbd8SKent Overstreet if (!bch2_csum_type_is_encryption(type)) 242a9de137bSKent Overstreet return 0; 2431c6fdbd8SKent Overstreet 244a9de137bSKent Overstreet return do_encrypt(c->chacha20, nonce, data, len); 2451c6fdbd8SKent Overstreet } 2461c6fdbd8SKent Overstreet 2471c6fdbd8SKent Overstreet static struct bch_csum __bch2_checksum_bio(struct bch_fs *c, unsigned type, 2481c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio, 2491c6fdbd8SKent Overstreet struct bvec_iter *iter) 2501c6fdbd8SKent Overstreet { 2511c6fdbd8SKent Overstreet struct bio_vec bv; 2521c6fdbd8SKent Overstreet 2531c6fdbd8SKent Overstreet switch (type) { 2546404dcc9SKent Overstreet case BCH_CSUM_none: 2551c6fdbd8SKent Overstreet return (struct bch_csum) { 0 }; 2566404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 2576404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 2586404dcc9SKent Overstreet case BCH_CSUM_crc32c: 2596404dcc9SKent Overstreet case BCH_CSUM_xxhash: 2606404dcc9SKent Overstreet case BCH_CSUM_crc64: { 26180ff5d18Sjpsollie struct bch2_checksum_state state; 26280ff5d18Sjpsollie 26380ff5d18Sjpsollie state.type = type; 26480ff5d18Sjpsollie bch2_checksum_init(&state); 2651c6fdbd8SKent Overstreet 2661c6fdbd8SKent Overstreet #ifdef CONFIG_HIGHMEM 2671c6fdbd8SKent Overstreet __bio_for_each_segment(bv, bio, *iter, *iter) { 2681e81f89bSKent Overstreet void *p = kmap_local_page(bv.bv_page) + bv.bv_offset; 2691e81f89bSKent Overstreet 27080ff5d18Sjpsollie bch2_checksum_update(&state, p, bv.bv_len); 2711e81f89bSKent Overstreet kunmap_local(p); 2721c6fdbd8SKent Overstreet } 2731c6fdbd8SKent Overstreet #else 2740fd7263eSKent Overstreet __bio_for_each_bvec(bv, bio, *iter, *iter) 27580ff5d18Sjpsollie bch2_checksum_update(&state, page_address(bv.bv_page) + bv.bv_offset, 2761c6fdbd8SKent Overstreet bv.bv_len); 2771c6fdbd8SKent Overstreet #endif 27880ff5d18Sjpsollie return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; 2791c6fdbd8SKent Overstreet } 2801c6fdbd8SKent Overstreet 2816404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_80: 2826404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_128: { 2831c6fdbd8SKent Overstreet SHASH_DESC_ON_STACK(desc, c->poly1305); 2841c6fdbd8SKent Overstreet u8 digest[POLY1305_DIGEST_SIZE]; 2851c6fdbd8SKent Overstreet struct bch_csum ret = { 0 }; 2861c6fdbd8SKent Overstreet 2871c6fdbd8SKent Overstreet gen_poly_key(c, desc, nonce); 2881c6fdbd8SKent Overstreet 2891c6fdbd8SKent Overstreet #ifdef CONFIG_HIGHMEM 2901c6fdbd8SKent Overstreet __bio_for_each_segment(bv, bio, *iter, *iter) { 2911e81f89bSKent Overstreet void *p = kmap_local_page(bv.bv_page) + bv.bv_offset; 2921c6fdbd8SKent Overstreet 2931c6fdbd8SKent Overstreet crypto_shash_update(desc, p, bv.bv_len); 2941e81f89bSKent Overstreet kunmap_local(p); 2951c6fdbd8SKent Overstreet } 2961c6fdbd8SKent Overstreet #else 2970fd7263eSKent Overstreet __bio_for_each_bvec(bv, bio, *iter, *iter) 2981c6fdbd8SKent Overstreet crypto_shash_update(desc, 2991c6fdbd8SKent Overstreet page_address(bv.bv_page) + bv.bv_offset, 3001c6fdbd8SKent Overstreet bv.bv_len); 3011c6fdbd8SKent Overstreet #endif 3021c6fdbd8SKent Overstreet crypto_shash_final(desc, digest); 3031c6fdbd8SKent Overstreet 3041c6fdbd8SKent Overstreet memcpy(&ret, digest, bch_crc_bytes[type]); 3051c6fdbd8SKent Overstreet return ret; 3061c6fdbd8SKent Overstreet } 3071c6fdbd8SKent Overstreet default: 3081c6fdbd8SKent Overstreet BUG(); 3091c6fdbd8SKent Overstreet } 3101c6fdbd8SKent Overstreet } 3111c6fdbd8SKent Overstreet 3121c6fdbd8SKent Overstreet struct bch_csum bch2_checksum_bio(struct bch_fs *c, unsigned type, 3131c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio) 3141c6fdbd8SKent Overstreet { 3151c6fdbd8SKent Overstreet struct bvec_iter iter = bio->bi_iter; 3161c6fdbd8SKent Overstreet 3171c6fdbd8SKent Overstreet return __bch2_checksum_bio(c, type, nonce, bio, &iter); 3181c6fdbd8SKent Overstreet } 3191c6fdbd8SKent Overstreet 3200cc455b3SKent Overstreet int __bch2_encrypt_bio(struct bch_fs *c, unsigned type, 3211c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio) 3221c6fdbd8SKent Overstreet { 3231c6fdbd8SKent Overstreet struct bio_vec bv; 3241c6fdbd8SKent Overstreet struct bvec_iter iter; 3251c6fdbd8SKent Overstreet struct scatterlist sgl[16], *sg = sgl; 3261c6fdbd8SKent Overstreet size_t bytes = 0; 327a9de137bSKent Overstreet int ret = 0; 3281c6fdbd8SKent Overstreet 3291c6fdbd8SKent Overstreet if (!bch2_csum_type_is_encryption(type)) 330a9de137bSKent Overstreet return 0; 3311c6fdbd8SKent Overstreet 3321c6fdbd8SKent Overstreet sg_init_table(sgl, ARRAY_SIZE(sgl)); 3331c6fdbd8SKent Overstreet 3341c6fdbd8SKent Overstreet bio_for_each_segment(bv, bio, iter) { 3351c6fdbd8SKent Overstreet if (sg == sgl + ARRAY_SIZE(sgl)) { 3361c6fdbd8SKent Overstreet sg_mark_end(sg - 1); 337a9de137bSKent Overstreet 338a9de137bSKent Overstreet ret = do_encrypt_sg(c->chacha20, nonce, sgl, bytes); 339a9de137bSKent Overstreet if (ret) 340a9de137bSKent Overstreet return ret; 3411c6fdbd8SKent Overstreet 3421c6fdbd8SKent Overstreet nonce = nonce_add(nonce, bytes); 3431c6fdbd8SKent Overstreet bytes = 0; 3441c6fdbd8SKent Overstreet 3451c6fdbd8SKent Overstreet sg_init_table(sgl, ARRAY_SIZE(sgl)); 3461c6fdbd8SKent Overstreet sg = sgl; 3471c6fdbd8SKent Overstreet } 3481c6fdbd8SKent Overstreet 3491c6fdbd8SKent Overstreet sg_set_page(sg++, bv.bv_page, bv.bv_len, bv.bv_offset); 3501c6fdbd8SKent Overstreet bytes += bv.bv_len; 3511c6fdbd8SKent Overstreet } 3521c6fdbd8SKent Overstreet 3531c6fdbd8SKent Overstreet sg_mark_end(sg - 1); 354a9de137bSKent Overstreet return do_encrypt_sg(c->chacha20, nonce, sgl, bytes); 3551c6fdbd8SKent Overstreet } 3561c6fdbd8SKent Overstreet 3576009b4e5SKent Overstreet struct bch_csum bch2_checksum_merge(unsigned type, struct bch_csum a, 3581c6fdbd8SKent Overstreet struct bch_csum b, size_t b_len) 3591c6fdbd8SKent Overstreet { 36080ff5d18Sjpsollie struct bch2_checksum_state state; 36180ff5d18Sjpsollie 36280ff5d18Sjpsollie state.type = type; 36380ff5d18Sjpsollie bch2_checksum_init(&state); 36473bd774dSKent Overstreet state.seed = (u64 __force) a.lo; 36580ff5d18Sjpsollie 3661c6fdbd8SKent Overstreet BUG_ON(!bch2_checksum_mergeable(type)); 3671c6fdbd8SKent Overstreet 3681c6fdbd8SKent Overstreet while (b_len) { 3691c6fdbd8SKent Overstreet unsigned b = min_t(unsigned, b_len, PAGE_SIZE); 3701c6fdbd8SKent Overstreet 37180ff5d18Sjpsollie bch2_checksum_update(&state, 3721c6fdbd8SKent Overstreet page_address(ZERO_PAGE(0)), b); 3731c6fdbd8SKent Overstreet b_len -= b; 3741c6fdbd8SKent Overstreet } 37573bd774dSKent Overstreet a.lo = (__le64 __force) bch2_checksum_final(&state); 3761c6fdbd8SKent Overstreet a.lo ^= b.lo; 3771c6fdbd8SKent Overstreet a.hi ^= b.hi; 3781c6fdbd8SKent Overstreet return a; 3791c6fdbd8SKent Overstreet } 3801c6fdbd8SKent Overstreet 3811c6fdbd8SKent Overstreet int bch2_rechecksum_bio(struct bch_fs *c, struct bio *bio, 3821c6fdbd8SKent Overstreet struct bversion version, 3831c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked crc_old, 3841c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc_a, 3851c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc_b, 3861c6fdbd8SKent Overstreet unsigned len_a, unsigned len_b, 3871c6fdbd8SKent Overstreet unsigned new_csum_type) 3881c6fdbd8SKent Overstreet { 3891c6fdbd8SKent Overstreet struct bvec_iter iter = bio->bi_iter; 3901c6fdbd8SKent Overstreet struct nonce nonce = extent_nonce(version, crc_old); 3911c6fdbd8SKent Overstreet struct bch_csum merged = { 0 }; 3921c6fdbd8SKent Overstreet struct crc_split { 3931c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc; 3941c6fdbd8SKent Overstreet unsigned len; 3951c6fdbd8SKent Overstreet unsigned csum_type; 3961c6fdbd8SKent Overstreet struct bch_csum csum; 3971c6fdbd8SKent Overstreet } splits[3] = { 3981c6fdbd8SKent Overstreet { crc_a, len_a, new_csum_type }, 3991c6fdbd8SKent Overstreet { crc_b, len_b, new_csum_type }, 4001c6fdbd8SKent Overstreet { NULL, bio_sectors(bio) - len_a - len_b, new_csum_type }, 4011c6fdbd8SKent Overstreet }, *i; 4021c6fdbd8SKent Overstreet bool mergeable = crc_old.csum_type == new_csum_type && 4031c6fdbd8SKent Overstreet bch2_checksum_mergeable(new_csum_type); 4041c6fdbd8SKent Overstreet unsigned crc_nonce = crc_old.nonce; 4051c6fdbd8SKent Overstreet 4061c6fdbd8SKent Overstreet BUG_ON(len_a + len_b > bio_sectors(bio)); 4071c6fdbd8SKent Overstreet BUG_ON(crc_old.uncompressed_size != bio_sectors(bio)); 408ab05de4cSKent Overstreet BUG_ON(crc_is_compressed(crc_old)); 4091c6fdbd8SKent Overstreet BUG_ON(bch2_csum_type_is_encryption(crc_old.csum_type) != 4101c6fdbd8SKent Overstreet bch2_csum_type_is_encryption(new_csum_type)); 4111c6fdbd8SKent Overstreet 4121c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) { 4131c6fdbd8SKent Overstreet iter.bi_size = i->len << 9; 4141c6fdbd8SKent Overstreet if (mergeable || i->crc) 4151c6fdbd8SKent Overstreet i->csum = __bch2_checksum_bio(c, i->csum_type, 4161c6fdbd8SKent Overstreet nonce, bio, &iter); 4171c6fdbd8SKent Overstreet else 4181c6fdbd8SKent Overstreet bio_advance_iter(bio, &iter, i->len << 9); 4191c6fdbd8SKent Overstreet nonce = nonce_add(nonce, i->len << 9); 4201c6fdbd8SKent Overstreet } 4211c6fdbd8SKent Overstreet 4221c6fdbd8SKent Overstreet if (mergeable) 4231c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) 4241c6fdbd8SKent Overstreet merged = bch2_checksum_merge(new_csum_type, merged, 4251c6fdbd8SKent Overstreet i->csum, i->len << 9); 4261c6fdbd8SKent Overstreet else 4271c6fdbd8SKent Overstreet merged = bch2_checksum_bio(c, crc_old.csum_type, 4281c6fdbd8SKent Overstreet extent_nonce(version, crc_old), bio); 4291c6fdbd8SKent Overstreet 430970a5096SKent Overstreet if (bch2_crc_cmp(merged, crc_old.csum) && !c->opts.no_data_io) { 4311e81f89bSKent Overstreet bch_err(c, "checksum error in %s() (memory corruption or bug?)\n" 43223189da9SKent Overstreet "expected %0llx:%0llx got %0llx:%0llx (old type %s new type %s)", 4331e81f89bSKent Overstreet __func__, 43423189da9SKent Overstreet crc_old.csum.hi, 43523189da9SKent Overstreet crc_old.csum.lo, 43623189da9SKent Overstreet merged.hi, 43723189da9SKent Overstreet merged.lo, 43823189da9SKent Overstreet bch2_csum_types[crc_old.csum_type], 43923189da9SKent Overstreet bch2_csum_types[new_csum_type]); 4401c6fdbd8SKent Overstreet return -EIO; 44123189da9SKent Overstreet } 4421c6fdbd8SKent Overstreet 4431c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) { 4441c6fdbd8SKent Overstreet if (i->crc) 4451c6fdbd8SKent Overstreet *i->crc = (struct bch_extent_crc_unpacked) { 4461c6fdbd8SKent Overstreet .csum_type = i->csum_type, 447ab05de4cSKent Overstreet .compression_type = crc_old.compression_type, 4481c6fdbd8SKent Overstreet .compressed_size = i->len, 4491c6fdbd8SKent Overstreet .uncompressed_size = i->len, 4501c6fdbd8SKent Overstreet .offset = 0, 4511c6fdbd8SKent Overstreet .live_size = i->len, 4521c6fdbd8SKent Overstreet .nonce = crc_nonce, 4531c6fdbd8SKent Overstreet .csum = i->csum, 4541c6fdbd8SKent Overstreet }; 4551c6fdbd8SKent Overstreet 4561c6fdbd8SKent Overstreet if (bch2_csum_type_is_encryption(new_csum_type)) 4571c6fdbd8SKent Overstreet crc_nonce += i->len; 4581c6fdbd8SKent Overstreet } 4591c6fdbd8SKent Overstreet 4601c6fdbd8SKent Overstreet return 0; 4611c6fdbd8SKent Overstreet } 4621c6fdbd8SKent Overstreet 463*0ec39856SKent Overstreet /* BCH_SB_FIELD_crypt: */ 464*0ec39856SKent Overstreet 465*0ec39856SKent Overstreet static int bch2_sb_crypt_validate(struct bch_sb *sb, 466*0ec39856SKent Overstreet struct bch_sb_field *f, 467*0ec39856SKent Overstreet struct printbuf *err) 468*0ec39856SKent Overstreet { 469*0ec39856SKent Overstreet struct bch_sb_field_crypt *crypt = field_to_type(f, crypt); 470*0ec39856SKent Overstreet 471*0ec39856SKent Overstreet if (vstruct_bytes(&crypt->field) < sizeof(*crypt)) { 472*0ec39856SKent Overstreet prt_printf(err, "wrong size (got %zu should be %zu)", 473*0ec39856SKent Overstreet vstruct_bytes(&crypt->field), sizeof(*crypt)); 474*0ec39856SKent Overstreet return -BCH_ERR_invalid_sb_crypt; 475*0ec39856SKent Overstreet } 476*0ec39856SKent Overstreet 477*0ec39856SKent Overstreet if (BCH_CRYPT_KDF_TYPE(crypt)) { 478*0ec39856SKent Overstreet prt_printf(err, "bad kdf type %llu", BCH_CRYPT_KDF_TYPE(crypt)); 479*0ec39856SKent Overstreet return -BCH_ERR_invalid_sb_crypt; 480*0ec39856SKent Overstreet } 481*0ec39856SKent Overstreet 482*0ec39856SKent Overstreet return 0; 483*0ec39856SKent Overstreet } 484*0ec39856SKent Overstreet 485*0ec39856SKent Overstreet static void bch2_sb_crypt_to_text(struct printbuf *out, struct bch_sb *sb, 486*0ec39856SKent Overstreet struct bch_sb_field *f) 487*0ec39856SKent Overstreet { 488*0ec39856SKent Overstreet struct bch_sb_field_crypt *crypt = field_to_type(f, crypt); 489*0ec39856SKent Overstreet 490*0ec39856SKent Overstreet prt_printf(out, "KFD: %llu", BCH_CRYPT_KDF_TYPE(crypt)); 491*0ec39856SKent Overstreet prt_newline(out); 492*0ec39856SKent Overstreet prt_printf(out, "scrypt n: %llu", BCH_KDF_SCRYPT_N(crypt)); 493*0ec39856SKent Overstreet prt_newline(out); 494*0ec39856SKent Overstreet prt_printf(out, "scrypt r: %llu", BCH_KDF_SCRYPT_R(crypt)); 495*0ec39856SKent Overstreet prt_newline(out); 496*0ec39856SKent Overstreet prt_printf(out, "scrypt p: %llu", BCH_KDF_SCRYPT_P(crypt)); 497*0ec39856SKent Overstreet prt_newline(out); 498*0ec39856SKent Overstreet } 499*0ec39856SKent Overstreet 500*0ec39856SKent Overstreet const struct bch_sb_field_ops bch_sb_field_ops_crypt = { 501*0ec39856SKent Overstreet .validate = bch2_sb_crypt_validate, 502*0ec39856SKent Overstreet .to_text = bch2_sb_crypt_to_text, 503*0ec39856SKent Overstreet }; 504*0ec39856SKent Overstreet 5051c6fdbd8SKent Overstreet #ifdef __KERNEL__ 50603ea3962SKent Overstreet static int __bch2_request_key(char *key_description, struct bch_key *key) 5071c6fdbd8SKent Overstreet { 5081c6fdbd8SKent Overstreet struct key *keyring_key; 5091c6fdbd8SKent Overstreet const struct user_key_payload *ukp; 5101c6fdbd8SKent Overstreet int ret; 5111c6fdbd8SKent Overstreet 512232697abSKent Overstreet keyring_key = request_key(&key_type_user, key_description, NULL); 5131c6fdbd8SKent Overstreet if (IS_ERR(keyring_key)) 5141c6fdbd8SKent Overstreet return PTR_ERR(keyring_key); 5151c6fdbd8SKent Overstreet 5161c6fdbd8SKent Overstreet down_read(&keyring_key->sem); 5171c6fdbd8SKent Overstreet ukp = dereference_key_locked(keyring_key); 5181c6fdbd8SKent Overstreet if (ukp->datalen == sizeof(*key)) { 5191c6fdbd8SKent Overstreet memcpy(key, ukp->data, ukp->datalen); 5201c6fdbd8SKent Overstreet ret = 0; 5211c6fdbd8SKent Overstreet } else { 5221c6fdbd8SKent Overstreet ret = -EINVAL; 5231c6fdbd8SKent Overstreet } 5241c6fdbd8SKent Overstreet up_read(&keyring_key->sem); 5251c6fdbd8SKent Overstreet key_put(keyring_key); 5261c6fdbd8SKent Overstreet 5271c6fdbd8SKent Overstreet return ret; 5281c6fdbd8SKent Overstreet } 5291c6fdbd8SKent Overstreet #else 5301c6fdbd8SKent Overstreet #include <keyutils.h> 5311c6fdbd8SKent Overstreet 53203ea3962SKent Overstreet static int __bch2_request_key(char *key_description, struct bch_key *key) 5331c6fdbd8SKent Overstreet { 5341c6fdbd8SKent Overstreet key_serial_t key_id; 5351c6fdbd8SKent Overstreet 5361c6fdbd8SKent Overstreet key_id = request_key("user", key_description, NULL, 5371c6fdbd8SKent Overstreet KEY_SPEC_USER_KEYRING); 5381c6fdbd8SKent Overstreet if (key_id < 0) 5391c6fdbd8SKent Overstreet return -errno; 5401c6fdbd8SKent Overstreet 5411c6fdbd8SKent Overstreet if (keyctl_read(key_id, (void *) key, sizeof(*key)) != sizeof(*key)) 5421c6fdbd8SKent Overstreet return -1; 5431c6fdbd8SKent Overstreet 5441c6fdbd8SKent Overstreet return 0; 5451c6fdbd8SKent Overstreet } 5461c6fdbd8SKent Overstreet #endif 5471c6fdbd8SKent Overstreet 54803ea3962SKent Overstreet int bch2_request_key(struct bch_sb *sb, struct bch_key *key) 54903ea3962SKent Overstreet { 550401ec4dbSKent Overstreet struct printbuf key_description = PRINTBUF; 551401ec4dbSKent Overstreet int ret; 55203ea3962SKent Overstreet 553401ec4dbSKent Overstreet prt_printf(&key_description, "bcachefs:"); 554401ec4dbSKent Overstreet pr_uuid(&key_description, sb->user_uuid.b); 55503ea3962SKent Overstreet 556401ec4dbSKent Overstreet ret = __bch2_request_key(key_description.buf, key); 557401ec4dbSKent Overstreet printbuf_exit(&key_description); 558401ec4dbSKent Overstreet return ret; 55903ea3962SKent Overstreet } 56003ea3962SKent Overstreet 5611c6fdbd8SKent Overstreet int bch2_decrypt_sb_key(struct bch_fs *c, 5621c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt, 5631c6fdbd8SKent Overstreet struct bch_key *key) 5641c6fdbd8SKent Overstreet { 5651c6fdbd8SKent Overstreet struct bch_encrypted_key sb_key = crypt->key; 5661c6fdbd8SKent Overstreet struct bch_key user_key; 5671c6fdbd8SKent Overstreet int ret = 0; 5681c6fdbd8SKent Overstreet 5691c6fdbd8SKent Overstreet /* is key encrypted? */ 5701c6fdbd8SKent Overstreet if (!bch2_key_is_encrypted(&sb_key)) 5711c6fdbd8SKent Overstreet goto out; 5721c6fdbd8SKent Overstreet 5731c6fdbd8SKent Overstreet ret = bch2_request_key(c->disk_sb.sb, &user_key); 5741c6fdbd8SKent Overstreet if (ret) { 575d4bf5eecSKent Overstreet bch_err(c, "error requesting encryption key: %s", bch2_err_str(ret)); 5761c6fdbd8SKent Overstreet goto err; 5771c6fdbd8SKent Overstreet } 5781c6fdbd8SKent Overstreet 5791c6fdbd8SKent Overstreet /* decrypt real key: */ 5801c6fdbd8SKent Overstreet ret = bch2_chacha_encrypt_key(&user_key, bch2_sb_key_nonce(c), 5811c6fdbd8SKent Overstreet &sb_key, sizeof(sb_key)); 5821c6fdbd8SKent Overstreet if (ret) 5831c6fdbd8SKent Overstreet goto err; 5841c6fdbd8SKent Overstreet 5851c6fdbd8SKent Overstreet if (bch2_key_is_encrypted(&sb_key)) { 5861c6fdbd8SKent Overstreet bch_err(c, "incorrect encryption key"); 5871c6fdbd8SKent Overstreet ret = -EINVAL; 5881c6fdbd8SKent Overstreet goto err; 5891c6fdbd8SKent Overstreet } 5901c6fdbd8SKent Overstreet out: 5911c6fdbd8SKent Overstreet *key = sb_key.key; 5921c6fdbd8SKent Overstreet err: 5931c6fdbd8SKent Overstreet memzero_explicit(&sb_key, sizeof(sb_key)); 5941c6fdbd8SKent Overstreet memzero_explicit(&user_key, sizeof(user_key)); 5951c6fdbd8SKent Overstreet return ret; 5961c6fdbd8SKent Overstreet } 5971c6fdbd8SKent Overstreet 5981c6fdbd8SKent Overstreet static int bch2_alloc_ciphers(struct bch_fs *c) 5991c6fdbd8SKent Overstreet { 600d4bf5eecSKent Overstreet int ret; 601d4bf5eecSKent Overstreet 6021c6fdbd8SKent Overstreet if (!c->chacha20) 6031c6fdbd8SKent Overstreet c->chacha20 = crypto_alloc_sync_skcipher("chacha20", 0, 0); 604d4bf5eecSKent Overstreet ret = PTR_ERR_OR_ZERO(c->chacha20); 605d4bf5eecSKent Overstreet 606d4bf5eecSKent Overstreet if (ret) { 607d4bf5eecSKent Overstreet bch_err(c, "error requesting chacha20 module: %s", bch2_err_str(ret)); 608d4bf5eecSKent Overstreet return ret; 6091c6fdbd8SKent Overstreet } 6101c6fdbd8SKent Overstreet 6111c6fdbd8SKent Overstreet if (!c->poly1305) 6121c6fdbd8SKent Overstreet c->poly1305 = crypto_alloc_shash("poly1305", 0, 0); 613d4bf5eecSKent Overstreet ret = PTR_ERR_OR_ZERO(c->poly1305); 614d4bf5eecSKent Overstreet 615d4bf5eecSKent Overstreet if (ret) { 616d4bf5eecSKent Overstreet bch_err(c, "error requesting poly1305 module: %s", bch2_err_str(ret)); 617d4bf5eecSKent Overstreet return ret; 6181c6fdbd8SKent Overstreet } 6191c6fdbd8SKent Overstreet 6201c6fdbd8SKent Overstreet return 0; 6211c6fdbd8SKent Overstreet } 6221c6fdbd8SKent Overstreet 6231c6fdbd8SKent Overstreet int bch2_disable_encryption(struct bch_fs *c) 6241c6fdbd8SKent Overstreet { 6251c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 6261c6fdbd8SKent Overstreet struct bch_key key; 6271c6fdbd8SKent Overstreet int ret = -EINVAL; 6281c6fdbd8SKent Overstreet 6291c6fdbd8SKent Overstreet mutex_lock(&c->sb_lock); 6301c6fdbd8SKent Overstreet 6311c6fdbd8SKent Overstreet crypt = bch2_sb_get_crypt(c->disk_sb.sb); 6321c6fdbd8SKent Overstreet if (!crypt) 6331c6fdbd8SKent Overstreet goto out; 6341c6fdbd8SKent Overstreet 6351c6fdbd8SKent Overstreet /* is key encrypted? */ 6361c6fdbd8SKent Overstreet ret = 0; 6371c6fdbd8SKent Overstreet if (bch2_key_is_encrypted(&crypt->key)) 6381c6fdbd8SKent Overstreet goto out; 6391c6fdbd8SKent Overstreet 6401c6fdbd8SKent Overstreet ret = bch2_decrypt_sb_key(c, crypt, &key); 6411c6fdbd8SKent Overstreet if (ret) 6421c6fdbd8SKent Overstreet goto out; 6431c6fdbd8SKent Overstreet 64473bd774dSKent Overstreet crypt->key.magic = cpu_to_le64(BCH_KEY_MAGIC); 6451c6fdbd8SKent Overstreet crypt->key.key = key; 6461c6fdbd8SKent Overstreet 6471c6fdbd8SKent Overstreet SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 0); 6481c6fdbd8SKent Overstreet bch2_write_super(c); 6491c6fdbd8SKent Overstreet out: 6501c6fdbd8SKent Overstreet mutex_unlock(&c->sb_lock); 6511c6fdbd8SKent Overstreet 6521c6fdbd8SKent Overstreet return ret; 6531c6fdbd8SKent Overstreet } 6541c6fdbd8SKent Overstreet 6551c6fdbd8SKent Overstreet int bch2_enable_encryption(struct bch_fs *c, bool keyed) 6561c6fdbd8SKent Overstreet { 6571c6fdbd8SKent Overstreet struct bch_encrypted_key key; 6581c6fdbd8SKent Overstreet struct bch_key user_key; 6591c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 6601c6fdbd8SKent Overstreet int ret = -EINVAL; 6611c6fdbd8SKent Overstreet 6621c6fdbd8SKent Overstreet mutex_lock(&c->sb_lock); 6631c6fdbd8SKent Overstreet 6641c6fdbd8SKent Overstreet /* Do we already have an encryption key? */ 6651c6fdbd8SKent Overstreet if (bch2_sb_get_crypt(c->disk_sb.sb)) 6661c6fdbd8SKent Overstreet goto err; 6671c6fdbd8SKent Overstreet 6681c6fdbd8SKent Overstreet ret = bch2_alloc_ciphers(c); 6691c6fdbd8SKent Overstreet if (ret) 6701c6fdbd8SKent Overstreet goto err; 6711c6fdbd8SKent Overstreet 67273bd774dSKent Overstreet key.magic = cpu_to_le64(BCH_KEY_MAGIC); 6731c6fdbd8SKent Overstreet get_random_bytes(&key.key, sizeof(key.key)); 6741c6fdbd8SKent Overstreet 6751c6fdbd8SKent Overstreet if (keyed) { 6761c6fdbd8SKent Overstreet ret = bch2_request_key(c->disk_sb.sb, &user_key); 6771c6fdbd8SKent Overstreet if (ret) { 678d4bf5eecSKent Overstreet bch_err(c, "error requesting encryption key: %s", bch2_err_str(ret)); 6791c6fdbd8SKent Overstreet goto err; 6801c6fdbd8SKent Overstreet } 6811c6fdbd8SKent Overstreet 6821c6fdbd8SKent Overstreet ret = bch2_chacha_encrypt_key(&user_key, bch2_sb_key_nonce(c), 6831c6fdbd8SKent Overstreet &key, sizeof(key)); 6841c6fdbd8SKent Overstreet if (ret) 6851c6fdbd8SKent Overstreet goto err; 6861c6fdbd8SKent Overstreet } 6871c6fdbd8SKent Overstreet 6881c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&c->chacha20->base, 6891c6fdbd8SKent Overstreet (void *) &key.key, sizeof(key.key)); 6901c6fdbd8SKent Overstreet if (ret) 6911c6fdbd8SKent Overstreet goto err; 6921c6fdbd8SKent Overstreet 6931c6fdbd8SKent Overstreet crypt = bch2_sb_resize_crypt(&c->disk_sb, sizeof(*crypt) / sizeof(u64)); 6941c6fdbd8SKent Overstreet if (!crypt) { 69565d48e35SKent Overstreet ret = -BCH_ERR_ENOSPC_sb_crypt; 6961c6fdbd8SKent Overstreet goto err; 6971c6fdbd8SKent Overstreet } 6981c6fdbd8SKent Overstreet 6991c6fdbd8SKent Overstreet crypt->key = key; 7001c6fdbd8SKent Overstreet 7011c6fdbd8SKent Overstreet /* write superblock */ 7021c6fdbd8SKent Overstreet SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 1); 7031c6fdbd8SKent Overstreet bch2_write_super(c); 7041c6fdbd8SKent Overstreet err: 7051c6fdbd8SKent Overstreet mutex_unlock(&c->sb_lock); 7061c6fdbd8SKent Overstreet memzero_explicit(&user_key, sizeof(user_key)); 7071c6fdbd8SKent Overstreet memzero_explicit(&key, sizeof(key)); 7081c6fdbd8SKent Overstreet return ret; 7091c6fdbd8SKent Overstreet } 7101c6fdbd8SKent Overstreet 7111c6fdbd8SKent Overstreet void bch2_fs_encryption_exit(struct bch_fs *c) 7121c6fdbd8SKent Overstreet { 7131c6fdbd8SKent Overstreet if (!IS_ERR_OR_NULL(c->poly1305)) 7141c6fdbd8SKent Overstreet crypto_free_shash(c->poly1305); 7151c6fdbd8SKent Overstreet if (!IS_ERR_OR_NULL(c->chacha20)) 7161c6fdbd8SKent Overstreet crypto_free_sync_skcipher(c->chacha20); 7171c6fdbd8SKent Overstreet if (!IS_ERR_OR_NULL(c->sha256)) 7181c6fdbd8SKent Overstreet crypto_free_shash(c->sha256); 7191c6fdbd8SKent Overstreet } 7201c6fdbd8SKent Overstreet 7211c6fdbd8SKent Overstreet int bch2_fs_encryption_init(struct bch_fs *c) 7221c6fdbd8SKent Overstreet { 7231c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 7241c6fdbd8SKent Overstreet struct bch_key key; 7251c6fdbd8SKent Overstreet int ret = 0; 7261c6fdbd8SKent Overstreet 7271c6fdbd8SKent Overstreet c->sha256 = crypto_alloc_shash("sha256", 0, 0); 728d4bf5eecSKent Overstreet ret = PTR_ERR_OR_ZERO(c->sha256); 729d4bf5eecSKent Overstreet if (ret) { 730d4bf5eecSKent Overstreet bch_err(c, "error requesting sha256 module: %s", bch2_err_str(ret)); 7311c6fdbd8SKent Overstreet goto out; 7321c6fdbd8SKent Overstreet } 7331c6fdbd8SKent Overstreet 7341c6fdbd8SKent Overstreet crypt = bch2_sb_get_crypt(c->disk_sb.sb); 7351c6fdbd8SKent Overstreet if (!crypt) 7361c6fdbd8SKent Overstreet goto out; 7371c6fdbd8SKent Overstreet 7381c6fdbd8SKent Overstreet ret = bch2_alloc_ciphers(c); 7391c6fdbd8SKent Overstreet if (ret) 7401c6fdbd8SKent Overstreet goto out; 7411c6fdbd8SKent Overstreet 7421c6fdbd8SKent Overstreet ret = bch2_decrypt_sb_key(c, crypt, &key); 7431c6fdbd8SKent Overstreet if (ret) 7441c6fdbd8SKent Overstreet goto out; 7451c6fdbd8SKent Overstreet 7461c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&c->chacha20->base, 7471c6fdbd8SKent Overstreet (void *) &key.key, sizeof(key.key)); 7481c6fdbd8SKent Overstreet if (ret) 7491c6fdbd8SKent Overstreet goto out; 7501c6fdbd8SKent Overstreet out: 7511c6fdbd8SKent Overstreet memzero_explicit(&key, sizeof(key)); 7521c6fdbd8SKent Overstreet return ret; 7531c6fdbd8SKent Overstreet } 754