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> 135e3c2083SKent Overstreet #include <linux/ratelimit.h> 141c6fdbd8SKent Overstreet #include <linux/scatterlist.h> 151c6fdbd8SKent Overstreet #include <crypto/algapi.h> 161c6fdbd8SKent Overstreet #include <crypto/chacha.h> 171c6fdbd8SKent Overstreet #include <crypto/hash.h> 181c6fdbd8SKent Overstreet #include <crypto/poly1305.h> 191c6fdbd8SKent Overstreet #include <crypto/skcipher.h> 201c6fdbd8SKent Overstreet #include <keys/user-type.h> 211c6fdbd8SKent Overstreet 2280ff5d18Sjpsollie /* 2380ff5d18Sjpsollie * bch2_checksum state is an abstraction of the checksum state calculated over different pages. 2480ff5d18Sjpsollie * it features page merging without having the checksum algorithm lose its state. 2580ff5d18Sjpsollie * for native checksum aglorithms (like crc), a default seed value will do. 2680ff5d18Sjpsollie * for hash-like algorithms, a state needs to be stored 2780ff5d18Sjpsollie */ 2880ff5d18Sjpsollie 2980ff5d18Sjpsollie struct bch2_checksum_state { 3080ff5d18Sjpsollie union { 3180ff5d18Sjpsollie u64 seed; 3241e63382Sjpsollie struct xxh64_state h64state; 3380ff5d18Sjpsollie }; 3480ff5d18Sjpsollie unsigned int type; 3580ff5d18Sjpsollie }; 3680ff5d18Sjpsollie 3780ff5d18Sjpsollie static void bch2_checksum_init(struct bch2_checksum_state *state) 381c6fdbd8SKent Overstreet { 3980ff5d18Sjpsollie switch (state->type) { 406404dcc9SKent Overstreet case BCH_CSUM_none: 416404dcc9SKent Overstreet case BCH_CSUM_crc32c: 426404dcc9SKent Overstreet case BCH_CSUM_crc64: 4380ff5d18Sjpsollie state->seed = 0; 4480ff5d18Sjpsollie break; 456404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 4680ff5d18Sjpsollie state->seed = U32_MAX; 4780ff5d18Sjpsollie break; 486404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 4980ff5d18Sjpsollie state->seed = U64_MAX; 5080ff5d18Sjpsollie break; 516404dcc9SKent Overstreet case BCH_CSUM_xxhash: 5241e63382Sjpsollie xxh64_reset(&state->h64state, 0); 5341e63382Sjpsollie break; 541c6fdbd8SKent Overstreet default: 551c6fdbd8SKent Overstreet BUG(); 561c6fdbd8SKent Overstreet } 571c6fdbd8SKent Overstreet } 581c6fdbd8SKent Overstreet 5980ff5d18Sjpsollie static u64 bch2_checksum_final(const struct bch2_checksum_state *state) 601c6fdbd8SKent Overstreet { 6180ff5d18Sjpsollie switch (state->type) { 626404dcc9SKent Overstreet case BCH_CSUM_none: 636404dcc9SKent Overstreet case BCH_CSUM_crc32c: 646404dcc9SKent Overstreet case BCH_CSUM_crc64: 6580ff5d18Sjpsollie return state->seed; 666404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 6780ff5d18Sjpsollie return state->seed ^ U32_MAX; 686404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 6980ff5d18Sjpsollie return state->seed ^ U64_MAX; 706404dcc9SKent Overstreet case BCH_CSUM_xxhash: 7141e63382Sjpsollie return xxh64_digest(&state->h64state); 721c6fdbd8SKent Overstreet default: 731c6fdbd8SKent Overstreet BUG(); 741c6fdbd8SKent Overstreet } 751c6fdbd8SKent Overstreet } 761c6fdbd8SKent Overstreet 7780ff5d18Sjpsollie static void bch2_checksum_update(struct bch2_checksum_state *state, const void *data, size_t len) 781c6fdbd8SKent Overstreet { 7980ff5d18Sjpsollie switch (state->type) { 806404dcc9SKent Overstreet case BCH_CSUM_none: 8180ff5d18Sjpsollie return; 826404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 836404dcc9SKent Overstreet case BCH_CSUM_crc32c: 8480ff5d18Sjpsollie state->seed = crc32c(state->seed, data, len); 8580ff5d18Sjpsollie break; 866404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 876404dcc9SKent Overstreet case BCH_CSUM_crc64: 8880ff5d18Sjpsollie state->seed = crc64_be(state->seed, data, len); 8980ff5d18Sjpsollie break; 906404dcc9SKent Overstreet case BCH_CSUM_xxhash: 9141e63382Sjpsollie xxh64_update(&state->h64state, data, len); 9241e63382Sjpsollie break; 931c6fdbd8SKent Overstreet default: 941c6fdbd8SKent Overstreet BUG(); 951c6fdbd8SKent Overstreet } 961c6fdbd8SKent Overstreet } 971c6fdbd8SKent Overstreet 98a9de137bSKent Overstreet static inline int do_encrypt_sg(struct crypto_sync_skcipher *tfm, 991c6fdbd8SKent Overstreet struct nonce nonce, 1001c6fdbd8SKent Overstreet struct scatterlist *sg, size_t len) 1011c6fdbd8SKent Overstreet { 1021c6fdbd8SKent Overstreet SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 1031c6fdbd8SKent Overstreet 1041c6fdbd8SKent Overstreet skcipher_request_set_sync_tfm(req, tfm); 10588ab1018SKent Overstreet skcipher_request_set_callback(req, 0, NULL, NULL); 1061c6fdbd8SKent Overstreet skcipher_request_set_crypt(req, sg, sg, len, nonce.d); 1071c6fdbd8SKent Overstreet 108b7d8092aSKent Overstreet int ret = crypto_skcipher_encrypt(req); 109a9de137bSKent Overstreet if (ret) 110a9de137bSKent Overstreet pr_err("got error %i from crypto_skcipher_encrypt()", ret); 111a9de137bSKent Overstreet 112a9de137bSKent Overstreet return ret; 1131c6fdbd8SKent Overstreet } 1141c6fdbd8SKent Overstreet 115a9de137bSKent Overstreet static inline int do_encrypt(struct crypto_sync_skcipher *tfm, 1161c6fdbd8SKent Overstreet struct nonce nonce, 1171c6fdbd8SKent Overstreet void *buf, size_t len) 1181c6fdbd8SKent Overstreet { 119636d4eefSKent Overstreet if (!is_vmalloc_addr(buf)) { 1201c6fdbd8SKent Overstreet struct scatterlist sg; 1211c6fdbd8SKent Overstreet 122c346def9SKent Overstreet sg_init_table(&sg, 1); 123c346def9SKent Overstreet sg_set_page(&sg, 124c346def9SKent Overstreet is_vmalloc_addr(buf) 125c346def9SKent Overstreet ? vmalloc_to_page(buf) 126c346def9SKent Overstreet : virt_to_page(buf), 127c346def9SKent Overstreet len, offset_in_page(buf)); 128a9de137bSKent Overstreet return do_encrypt_sg(tfm, nonce, &sg, len); 129636d4eefSKent Overstreet } else { 130b7d8092aSKent Overstreet DARRAY_PREALLOCATED(struct scatterlist, 4) sgl; 131b7d8092aSKent Overstreet size_t sgl_len = 0; 132b7d8092aSKent Overstreet int ret; 133636d4eefSKent Overstreet 134b7d8092aSKent Overstreet darray_init(&sgl); 135636d4eefSKent Overstreet 136b7d8092aSKent Overstreet while (len) { 137636d4eefSKent Overstreet unsigned offset = offset_in_page(buf); 138b7d8092aSKent Overstreet struct scatterlist sg = { 139b7d8092aSKent Overstreet .page_link = (unsigned long) vmalloc_to_page(buf), 140b7d8092aSKent Overstreet .offset = offset, 141b7d8092aSKent Overstreet .length = min(len, PAGE_SIZE - offset), 142b7d8092aSKent Overstreet }; 143636d4eefSKent Overstreet 144b7d8092aSKent Overstreet if (darray_push(&sgl, sg)) { 145b7d8092aSKent Overstreet sg_mark_end(&darray_last(sgl)); 146b7d8092aSKent Overstreet ret = do_encrypt_sg(tfm, nonce, sgl.data, sgl_len); 147b7d8092aSKent Overstreet if (ret) 148b7d8092aSKent Overstreet goto err; 149b7d8092aSKent Overstreet 150b7d8092aSKent Overstreet nonce = nonce_add(nonce, sgl_len); 151b7d8092aSKent Overstreet sgl_len = 0; 152b7d8092aSKent Overstreet sgl.nr = 0; 153b7d8092aSKent Overstreet BUG_ON(darray_push(&sgl, sg)); 154636d4eefSKent Overstreet } 155636d4eefSKent Overstreet 156b7d8092aSKent Overstreet buf += sg.length; 157b7d8092aSKent Overstreet len -= sg.length; 158b7d8092aSKent Overstreet sgl_len += sg.length; 159b7d8092aSKent Overstreet } 160b7d8092aSKent Overstreet 161b7d8092aSKent Overstreet sg_mark_end(&darray_last(sgl)); 162b7d8092aSKent Overstreet ret = do_encrypt_sg(tfm, nonce, sgl.data, sgl_len); 163b7d8092aSKent Overstreet err: 164b7d8092aSKent Overstreet darray_exit(&sgl); 165636d4eefSKent Overstreet return ret; 166636d4eefSKent Overstreet } 1671c6fdbd8SKent Overstreet } 1681c6fdbd8SKent Overstreet 1691c6fdbd8SKent Overstreet int bch2_chacha_encrypt_key(struct bch_key *key, struct nonce nonce, 1701c6fdbd8SKent Overstreet void *buf, size_t len) 1711c6fdbd8SKent Overstreet { 1721c6fdbd8SKent Overstreet struct crypto_sync_skcipher *chacha20 = 1731c6fdbd8SKent Overstreet crypto_alloc_sync_skcipher("chacha20", 0, 0); 1741c6fdbd8SKent Overstreet int ret; 1751c6fdbd8SKent Overstreet 17675e0c478SKent Overstreet ret = PTR_ERR_OR_ZERO(chacha20); 17775e0c478SKent Overstreet if (ret) { 17875e0c478SKent Overstreet pr_err("error requesting chacha20 cipher: %s", bch2_err_str(ret)); 17975e0c478SKent Overstreet return ret; 1801c6fdbd8SKent Overstreet } 1811c6fdbd8SKent Overstreet 1821c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&chacha20->base, 1831c6fdbd8SKent Overstreet (void *) key, sizeof(*key)); 1841c6fdbd8SKent Overstreet if (ret) { 18575e0c478SKent Overstreet pr_err("error from crypto_skcipher_setkey(): %s", bch2_err_str(ret)); 1861c6fdbd8SKent Overstreet goto err; 1871c6fdbd8SKent Overstreet } 1881c6fdbd8SKent Overstreet 189a9de137bSKent Overstreet ret = do_encrypt(chacha20, nonce, buf, len); 1901c6fdbd8SKent Overstreet err: 1911c6fdbd8SKent Overstreet crypto_free_sync_skcipher(chacha20); 1921c6fdbd8SKent Overstreet return ret; 1931c6fdbd8SKent Overstreet } 1941c6fdbd8SKent Overstreet 195a9de137bSKent Overstreet static int gen_poly_key(struct bch_fs *c, struct shash_desc *desc, 1961c6fdbd8SKent Overstreet struct nonce nonce) 1971c6fdbd8SKent Overstreet { 1981c6fdbd8SKent Overstreet u8 key[POLY1305_KEY_SIZE]; 199a9de137bSKent Overstreet int ret; 2001c6fdbd8SKent Overstreet 2011c6fdbd8SKent Overstreet nonce.d[3] ^= BCH_NONCE_POLY; 2021c6fdbd8SKent Overstreet 2031c6fdbd8SKent Overstreet memset(key, 0, sizeof(key)); 204a9de137bSKent Overstreet ret = do_encrypt(c->chacha20, nonce, key, sizeof(key)); 205a9de137bSKent Overstreet if (ret) 206a9de137bSKent Overstreet return ret; 2071c6fdbd8SKent Overstreet 2081c6fdbd8SKent Overstreet desc->tfm = c->poly1305; 2091c6fdbd8SKent Overstreet crypto_shash_init(desc); 2101c6fdbd8SKent Overstreet crypto_shash_update(desc, key, sizeof(key)); 211a9de137bSKent Overstreet return 0; 2121c6fdbd8SKent Overstreet } 2131c6fdbd8SKent Overstreet 2141c6fdbd8SKent Overstreet struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type, 2151c6fdbd8SKent Overstreet struct nonce nonce, const void *data, size_t len) 2161c6fdbd8SKent Overstreet { 2171c6fdbd8SKent Overstreet switch (type) { 2186404dcc9SKent Overstreet case BCH_CSUM_none: 2196404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 2206404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 2216404dcc9SKent Overstreet case BCH_CSUM_crc32c: 2226404dcc9SKent Overstreet case BCH_CSUM_xxhash: 2236404dcc9SKent Overstreet case BCH_CSUM_crc64: { 22480ff5d18Sjpsollie struct bch2_checksum_state state; 2251c6fdbd8SKent Overstreet 22680ff5d18Sjpsollie state.type = type; 2271c6fdbd8SKent Overstreet 22880ff5d18Sjpsollie bch2_checksum_init(&state); 22980ff5d18Sjpsollie bch2_checksum_update(&state, data, len); 23080ff5d18Sjpsollie 23180ff5d18Sjpsollie return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; 2321c6fdbd8SKent Overstreet } 2331c6fdbd8SKent Overstreet 2346404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_80: 2356404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_128: { 2361c6fdbd8SKent Overstreet SHASH_DESC_ON_STACK(desc, c->poly1305); 2371c6fdbd8SKent Overstreet u8 digest[POLY1305_DIGEST_SIZE]; 2381c6fdbd8SKent Overstreet struct bch_csum ret = { 0 }; 2391c6fdbd8SKent Overstreet 2401c6fdbd8SKent Overstreet gen_poly_key(c, desc, nonce); 2411c6fdbd8SKent Overstreet 2421c6fdbd8SKent Overstreet crypto_shash_update(desc, data, len); 2431c6fdbd8SKent Overstreet crypto_shash_final(desc, digest); 2441c6fdbd8SKent Overstreet 2451c6fdbd8SKent Overstreet memcpy(&ret, digest, bch_crc_bytes[type]); 2461c6fdbd8SKent Overstreet return ret; 2471c6fdbd8SKent Overstreet } 2481c6fdbd8SKent Overstreet default: 2496b74fdccSKent Overstreet return (struct bch_csum) {}; 2501c6fdbd8SKent Overstreet } 2511c6fdbd8SKent Overstreet } 2521c6fdbd8SKent Overstreet 253a9de137bSKent Overstreet int bch2_encrypt(struct bch_fs *c, unsigned type, 2541c6fdbd8SKent Overstreet struct nonce nonce, void *data, size_t len) 2551c6fdbd8SKent Overstreet { 2561c6fdbd8SKent Overstreet if (!bch2_csum_type_is_encryption(type)) 257a9de137bSKent Overstreet return 0; 2581c6fdbd8SKent Overstreet 259a9de137bSKent Overstreet return do_encrypt(c->chacha20, nonce, data, len); 2601c6fdbd8SKent Overstreet } 2611c6fdbd8SKent Overstreet 2621c6fdbd8SKent Overstreet static struct bch_csum __bch2_checksum_bio(struct bch_fs *c, unsigned type, 2631c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio, 2641c6fdbd8SKent Overstreet struct bvec_iter *iter) 2651c6fdbd8SKent Overstreet { 2661c6fdbd8SKent Overstreet struct bio_vec bv; 2671c6fdbd8SKent Overstreet 2681c6fdbd8SKent Overstreet switch (type) { 2696404dcc9SKent Overstreet case BCH_CSUM_none: 2701c6fdbd8SKent Overstreet return (struct bch_csum) { 0 }; 2716404dcc9SKent Overstreet case BCH_CSUM_crc32c_nonzero: 2726404dcc9SKent Overstreet case BCH_CSUM_crc64_nonzero: 2736404dcc9SKent Overstreet case BCH_CSUM_crc32c: 2746404dcc9SKent Overstreet case BCH_CSUM_xxhash: 2756404dcc9SKent Overstreet case BCH_CSUM_crc64: { 27680ff5d18Sjpsollie struct bch2_checksum_state state; 27780ff5d18Sjpsollie 27880ff5d18Sjpsollie state.type = type; 27980ff5d18Sjpsollie bch2_checksum_init(&state); 2801c6fdbd8SKent Overstreet 2811c6fdbd8SKent Overstreet #ifdef CONFIG_HIGHMEM 2821c6fdbd8SKent Overstreet __bio_for_each_segment(bv, bio, *iter, *iter) { 2831e81f89bSKent Overstreet void *p = kmap_local_page(bv.bv_page) + bv.bv_offset; 2841e81f89bSKent Overstreet 28580ff5d18Sjpsollie bch2_checksum_update(&state, p, bv.bv_len); 2861e81f89bSKent Overstreet kunmap_local(p); 2871c6fdbd8SKent Overstreet } 2881c6fdbd8SKent Overstreet #else 2890fd7263eSKent Overstreet __bio_for_each_bvec(bv, bio, *iter, *iter) 29080ff5d18Sjpsollie bch2_checksum_update(&state, page_address(bv.bv_page) + bv.bv_offset, 2911c6fdbd8SKent Overstreet bv.bv_len); 2921c6fdbd8SKent Overstreet #endif 29380ff5d18Sjpsollie return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; 2941c6fdbd8SKent Overstreet } 2951c6fdbd8SKent Overstreet 2966404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_80: 2976404dcc9SKent Overstreet case BCH_CSUM_chacha20_poly1305_128: { 2981c6fdbd8SKent Overstreet SHASH_DESC_ON_STACK(desc, c->poly1305); 2991c6fdbd8SKent Overstreet u8 digest[POLY1305_DIGEST_SIZE]; 3001c6fdbd8SKent Overstreet struct bch_csum ret = { 0 }; 3011c6fdbd8SKent Overstreet 3021c6fdbd8SKent Overstreet gen_poly_key(c, desc, nonce); 3031c6fdbd8SKent Overstreet 3041c6fdbd8SKent Overstreet #ifdef CONFIG_HIGHMEM 3051c6fdbd8SKent Overstreet __bio_for_each_segment(bv, bio, *iter, *iter) { 3061e81f89bSKent Overstreet void *p = kmap_local_page(bv.bv_page) + bv.bv_offset; 3071c6fdbd8SKent Overstreet 3081c6fdbd8SKent Overstreet crypto_shash_update(desc, p, bv.bv_len); 3091e81f89bSKent Overstreet kunmap_local(p); 3101c6fdbd8SKent Overstreet } 3111c6fdbd8SKent Overstreet #else 3120fd7263eSKent Overstreet __bio_for_each_bvec(bv, bio, *iter, *iter) 3131c6fdbd8SKent Overstreet crypto_shash_update(desc, 3141c6fdbd8SKent Overstreet page_address(bv.bv_page) + bv.bv_offset, 3151c6fdbd8SKent Overstreet bv.bv_len); 3161c6fdbd8SKent Overstreet #endif 3171c6fdbd8SKent Overstreet crypto_shash_final(desc, digest); 3181c6fdbd8SKent Overstreet 3191c6fdbd8SKent Overstreet memcpy(&ret, digest, bch_crc_bytes[type]); 3201c6fdbd8SKent Overstreet return ret; 3211c6fdbd8SKent Overstreet } 3221c6fdbd8SKent Overstreet default: 3236b74fdccSKent Overstreet return (struct bch_csum) {}; 3241c6fdbd8SKent Overstreet } 3251c6fdbd8SKent Overstreet } 3261c6fdbd8SKent Overstreet 3271c6fdbd8SKent Overstreet struct bch_csum bch2_checksum_bio(struct bch_fs *c, unsigned type, 3281c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio) 3291c6fdbd8SKent Overstreet { 3301c6fdbd8SKent Overstreet struct bvec_iter iter = bio->bi_iter; 3311c6fdbd8SKent Overstreet 3321c6fdbd8SKent Overstreet return __bch2_checksum_bio(c, type, nonce, bio, &iter); 3331c6fdbd8SKent Overstreet } 3341c6fdbd8SKent Overstreet 3350cc455b3SKent Overstreet int __bch2_encrypt_bio(struct bch_fs *c, unsigned type, 3361c6fdbd8SKent Overstreet struct nonce nonce, struct bio *bio) 3371c6fdbd8SKent Overstreet { 3381c6fdbd8SKent Overstreet struct bio_vec bv; 3391c6fdbd8SKent Overstreet struct bvec_iter iter; 340*af05633dSKent Overstreet DARRAY_PREALLOCATED(struct scatterlist, 4) sgl; 341*af05633dSKent Overstreet size_t sgl_len = 0; 342a9de137bSKent Overstreet int ret = 0; 3431c6fdbd8SKent Overstreet 3441c6fdbd8SKent Overstreet if (!bch2_csum_type_is_encryption(type)) 345a9de137bSKent Overstreet return 0; 3461c6fdbd8SKent Overstreet 347*af05633dSKent Overstreet darray_init(&sgl); 3481c6fdbd8SKent Overstreet 3491c6fdbd8SKent Overstreet bio_for_each_segment(bv, bio, iter) { 350*af05633dSKent Overstreet struct scatterlist sg = { 351*af05633dSKent Overstreet .page_link = (unsigned long) bv.bv_page, 352*af05633dSKent Overstreet .offset = bv.bv_offset, 353*af05633dSKent Overstreet .length = bv.bv_len, 354*af05633dSKent Overstreet }; 355a9de137bSKent Overstreet 356*af05633dSKent Overstreet if (darray_push(&sgl, sg)) { 357*af05633dSKent Overstreet sg_mark_end(&darray_last(sgl)); 358*af05633dSKent Overstreet ret = do_encrypt_sg(c->chacha20, nonce, sgl.data, sgl_len); 359a9de137bSKent Overstreet if (ret) 360*af05633dSKent Overstreet goto err; 3611c6fdbd8SKent Overstreet 362*af05633dSKent Overstreet nonce = nonce_add(nonce, sgl_len); 363*af05633dSKent Overstreet sgl_len = 0; 364*af05633dSKent Overstreet sgl.nr = 0; 3651c6fdbd8SKent Overstreet 366*af05633dSKent Overstreet BUG_ON(darray_push(&sgl, sg)); 3671c6fdbd8SKent Overstreet } 3681c6fdbd8SKent Overstreet 369*af05633dSKent Overstreet sgl_len += sg.length; 3701c6fdbd8SKent Overstreet } 3711c6fdbd8SKent Overstreet 372*af05633dSKent Overstreet sg_mark_end(&darray_last(sgl)); 373*af05633dSKent Overstreet ret = do_encrypt_sg(c->chacha20, nonce, sgl.data, sgl_len); 374*af05633dSKent Overstreet err: 375*af05633dSKent Overstreet darray_exit(&sgl); 3762ba24864SKent Overstreet return ret; 3772ba24864SKent Overstreet } 3782ba24864SKent Overstreet 3796009b4e5SKent Overstreet struct bch_csum bch2_checksum_merge(unsigned type, struct bch_csum a, 3801c6fdbd8SKent Overstreet struct bch_csum b, size_t b_len) 3811c6fdbd8SKent Overstreet { 38280ff5d18Sjpsollie struct bch2_checksum_state state; 38380ff5d18Sjpsollie 38480ff5d18Sjpsollie state.type = type; 38580ff5d18Sjpsollie bch2_checksum_init(&state); 3863c40841cSBrian Foster state.seed = le64_to_cpu(a.lo); 38780ff5d18Sjpsollie 3881c6fdbd8SKent Overstreet BUG_ON(!bch2_checksum_mergeable(type)); 3891c6fdbd8SKent Overstreet 3901c6fdbd8SKent Overstreet while (b_len) { 39196dea3d5SKent Overstreet unsigned page_len = min_t(unsigned, b_len, PAGE_SIZE); 3921c6fdbd8SKent Overstreet 39380ff5d18Sjpsollie bch2_checksum_update(&state, 39496dea3d5SKent Overstreet page_address(ZERO_PAGE(0)), page_len); 39596dea3d5SKent Overstreet b_len -= page_len; 3961c6fdbd8SKent Overstreet } 3973c40841cSBrian Foster a.lo = cpu_to_le64(bch2_checksum_final(&state)); 3981c6fdbd8SKent Overstreet a.lo ^= b.lo; 3991c6fdbd8SKent Overstreet a.hi ^= b.hi; 4001c6fdbd8SKent Overstreet return a; 4011c6fdbd8SKent Overstreet } 4021c6fdbd8SKent Overstreet 4031c6fdbd8SKent Overstreet int bch2_rechecksum_bio(struct bch_fs *c, struct bio *bio, 4041c6fdbd8SKent Overstreet struct bversion version, 4051c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked crc_old, 4061c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc_a, 4071c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc_b, 4081c6fdbd8SKent Overstreet unsigned len_a, unsigned len_b, 4091c6fdbd8SKent Overstreet unsigned new_csum_type) 4101c6fdbd8SKent Overstreet { 4111c6fdbd8SKent Overstreet struct bvec_iter iter = bio->bi_iter; 4121c6fdbd8SKent Overstreet struct nonce nonce = extent_nonce(version, crc_old); 4131c6fdbd8SKent Overstreet struct bch_csum merged = { 0 }; 4141c6fdbd8SKent Overstreet struct crc_split { 4151c6fdbd8SKent Overstreet struct bch_extent_crc_unpacked *crc; 4161c6fdbd8SKent Overstreet unsigned len; 4171c6fdbd8SKent Overstreet unsigned csum_type; 4181c6fdbd8SKent Overstreet struct bch_csum csum; 4191c6fdbd8SKent Overstreet } splits[3] = { 42096dea3d5SKent Overstreet { crc_a, len_a, new_csum_type, { 0 }}, 42196dea3d5SKent Overstreet { crc_b, len_b, new_csum_type, { 0 } }, 42296dea3d5SKent Overstreet { NULL, bio_sectors(bio) - len_a - len_b, new_csum_type, { 0 } }, 4231c6fdbd8SKent Overstreet }, *i; 4241c6fdbd8SKent Overstreet bool mergeable = crc_old.csum_type == new_csum_type && 4251c6fdbd8SKent Overstreet bch2_checksum_mergeable(new_csum_type); 4261c6fdbd8SKent Overstreet unsigned crc_nonce = crc_old.nonce; 4271c6fdbd8SKent Overstreet 4281c6fdbd8SKent Overstreet BUG_ON(len_a + len_b > bio_sectors(bio)); 4291c6fdbd8SKent Overstreet BUG_ON(crc_old.uncompressed_size != bio_sectors(bio)); 430ab05de4cSKent Overstreet BUG_ON(crc_is_compressed(crc_old)); 4311c6fdbd8SKent Overstreet BUG_ON(bch2_csum_type_is_encryption(crc_old.csum_type) != 4321c6fdbd8SKent Overstreet bch2_csum_type_is_encryption(new_csum_type)); 4331c6fdbd8SKent Overstreet 4341c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) { 4351c6fdbd8SKent Overstreet iter.bi_size = i->len << 9; 4361c6fdbd8SKent Overstreet if (mergeable || i->crc) 4371c6fdbd8SKent Overstreet i->csum = __bch2_checksum_bio(c, i->csum_type, 4381c6fdbd8SKent Overstreet nonce, bio, &iter); 4391c6fdbd8SKent Overstreet else 4401c6fdbd8SKent Overstreet bio_advance_iter(bio, &iter, i->len << 9); 4411c6fdbd8SKent Overstreet nonce = nonce_add(nonce, i->len << 9); 4421c6fdbd8SKent Overstreet } 4431c6fdbd8SKent Overstreet 4441c6fdbd8SKent Overstreet if (mergeable) 4451c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) 4461c6fdbd8SKent Overstreet merged = bch2_checksum_merge(new_csum_type, merged, 4471c6fdbd8SKent Overstreet i->csum, i->len << 9); 4481c6fdbd8SKent Overstreet else 4491c6fdbd8SKent Overstreet merged = bch2_checksum_bio(c, crc_old.csum_type, 4501c6fdbd8SKent Overstreet extent_nonce(version, crc_old), bio); 4511c6fdbd8SKent Overstreet 452970a5096SKent Overstreet if (bch2_crc_cmp(merged, crc_old.csum) && !c->opts.no_data_io) { 4539abb6dd7SKent Overstreet struct printbuf buf = PRINTBUF; 4549abb6dd7SKent Overstreet prt_printf(&buf, "checksum error in %s() (memory corruption or bug?)\n" 4559abb6dd7SKent Overstreet " expected %0llx:%0llx got %0llx:%0llx (old type ", 4561e81f89bSKent Overstreet __func__, 45723189da9SKent Overstreet crc_old.csum.hi, 45823189da9SKent Overstreet crc_old.csum.lo, 45923189da9SKent Overstreet merged.hi, 4609abb6dd7SKent Overstreet merged.lo); 4619abb6dd7SKent Overstreet bch2_prt_csum_type(&buf, crc_old.csum_type); 4629abb6dd7SKent Overstreet prt_str(&buf, " new type "); 4639abb6dd7SKent Overstreet bch2_prt_csum_type(&buf, new_csum_type); 4649abb6dd7SKent Overstreet prt_str(&buf, ")"); 4655e3c2083SKent Overstreet WARN_RATELIMIT(1, "%s", buf.buf); 4669abb6dd7SKent Overstreet printbuf_exit(&buf); 4671c6fdbd8SKent Overstreet return -EIO; 46823189da9SKent Overstreet } 4691c6fdbd8SKent Overstreet 4701c6fdbd8SKent Overstreet for (i = splits; i < splits + ARRAY_SIZE(splits); i++) { 4711c6fdbd8SKent Overstreet if (i->crc) 4721c6fdbd8SKent Overstreet *i->crc = (struct bch_extent_crc_unpacked) { 4731c6fdbd8SKent Overstreet .csum_type = i->csum_type, 474ab05de4cSKent Overstreet .compression_type = crc_old.compression_type, 4751c6fdbd8SKent Overstreet .compressed_size = i->len, 4761c6fdbd8SKent Overstreet .uncompressed_size = i->len, 4771c6fdbd8SKent Overstreet .offset = 0, 4781c6fdbd8SKent Overstreet .live_size = i->len, 4791c6fdbd8SKent Overstreet .nonce = crc_nonce, 4801c6fdbd8SKent Overstreet .csum = i->csum, 4811c6fdbd8SKent Overstreet }; 4821c6fdbd8SKent Overstreet 4831c6fdbd8SKent Overstreet if (bch2_csum_type_is_encryption(new_csum_type)) 4841c6fdbd8SKent Overstreet crc_nonce += i->len; 4851c6fdbd8SKent Overstreet } 4861c6fdbd8SKent Overstreet 4871c6fdbd8SKent Overstreet return 0; 4881c6fdbd8SKent Overstreet } 4891c6fdbd8SKent Overstreet 4900ec39856SKent Overstreet /* BCH_SB_FIELD_crypt: */ 4910ec39856SKent Overstreet 492a5c3e265SKent Overstreet static int bch2_sb_crypt_validate(struct bch_sb *sb, struct bch_sb_field *f, 493a5c3e265SKent Overstreet enum bch_validate_flags flags, struct printbuf *err) 4940ec39856SKent Overstreet { 4950ec39856SKent Overstreet struct bch_sb_field_crypt *crypt = field_to_type(f, crypt); 4960ec39856SKent Overstreet 4970ec39856SKent Overstreet if (vstruct_bytes(&crypt->field) < sizeof(*crypt)) { 4980ec39856SKent Overstreet prt_printf(err, "wrong size (got %zu should be %zu)", 4990ec39856SKent Overstreet vstruct_bytes(&crypt->field), sizeof(*crypt)); 5000ec39856SKent Overstreet return -BCH_ERR_invalid_sb_crypt; 5010ec39856SKent Overstreet } 5020ec39856SKent Overstreet 5030ec39856SKent Overstreet if (BCH_CRYPT_KDF_TYPE(crypt)) { 5040ec39856SKent Overstreet prt_printf(err, "bad kdf type %llu", BCH_CRYPT_KDF_TYPE(crypt)); 5050ec39856SKent Overstreet return -BCH_ERR_invalid_sb_crypt; 5060ec39856SKent Overstreet } 5070ec39856SKent Overstreet 5080ec39856SKent Overstreet return 0; 5090ec39856SKent Overstreet } 5100ec39856SKent Overstreet 5110ec39856SKent Overstreet static void bch2_sb_crypt_to_text(struct printbuf *out, struct bch_sb *sb, 5120ec39856SKent Overstreet struct bch_sb_field *f) 5130ec39856SKent Overstreet { 5140ec39856SKent Overstreet struct bch_sb_field_crypt *crypt = field_to_type(f, crypt); 5150ec39856SKent Overstreet 5167423330eSKent Overstreet prt_printf(out, "KFD: %llu\n", BCH_CRYPT_KDF_TYPE(crypt)); 5177423330eSKent Overstreet prt_printf(out, "scrypt n: %llu\n", BCH_KDF_SCRYPT_N(crypt)); 5187423330eSKent Overstreet prt_printf(out, "scrypt r: %llu\n", BCH_KDF_SCRYPT_R(crypt)); 5197423330eSKent Overstreet prt_printf(out, "scrypt p: %llu\n", BCH_KDF_SCRYPT_P(crypt)); 5200ec39856SKent Overstreet } 5210ec39856SKent Overstreet 5220ec39856SKent Overstreet const struct bch_sb_field_ops bch_sb_field_ops_crypt = { 5230ec39856SKent Overstreet .validate = bch2_sb_crypt_validate, 5240ec39856SKent Overstreet .to_text = bch2_sb_crypt_to_text, 5250ec39856SKent Overstreet }; 5260ec39856SKent Overstreet 5271c6fdbd8SKent Overstreet #ifdef __KERNEL__ 52803ea3962SKent Overstreet static int __bch2_request_key(char *key_description, struct bch_key *key) 5291c6fdbd8SKent Overstreet { 5301c6fdbd8SKent Overstreet struct key *keyring_key; 5311c6fdbd8SKent Overstreet const struct user_key_payload *ukp; 5321c6fdbd8SKent Overstreet int ret; 5331c6fdbd8SKent Overstreet 534232697abSKent Overstreet keyring_key = request_key(&key_type_user, key_description, NULL); 5351c6fdbd8SKent Overstreet if (IS_ERR(keyring_key)) 5361c6fdbd8SKent Overstreet return PTR_ERR(keyring_key); 5371c6fdbd8SKent Overstreet 5381c6fdbd8SKent Overstreet down_read(&keyring_key->sem); 5391c6fdbd8SKent Overstreet ukp = dereference_key_locked(keyring_key); 5401c6fdbd8SKent Overstreet if (ukp->datalen == sizeof(*key)) { 5411c6fdbd8SKent Overstreet memcpy(key, ukp->data, ukp->datalen); 5421c6fdbd8SKent Overstreet ret = 0; 5431c6fdbd8SKent Overstreet } else { 5441c6fdbd8SKent Overstreet ret = -EINVAL; 5451c6fdbd8SKent Overstreet } 5461c6fdbd8SKent Overstreet up_read(&keyring_key->sem); 5471c6fdbd8SKent Overstreet key_put(keyring_key); 5481c6fdbd8SKent Overstreet 5491c6fdbd8SKent Overstreet return ret; 5501c6fdbd8SKent Overstreet } 5511c6fdbd8SKent Overstreet #else 5521c6fdbd8SKent Overstreet #include <keyutils.h> 5531c6fdbd8SKent Overstreet 55403ea3962SKent Overstreet static int __bch2_request_key(char *key_description, struct bch_key *key) 5551c6fdbd8SKent Overstreet { 5561c6fdbd8SKent Overstreet key_serial_t key_id; 5571c6fdbd8SKent Overstreet 5581c6fdbd8SKent Overstreet key_id = request_key("user", key_description, NULL, 5591ee608c6SKent Overstreet KEY_SPEC_SESSION_KEYRING); 5601ee608c6SKent Overstreet if (key_id >= 0) 5611ee608c6SKent Overstreet goto got_key; 5621ee608c6SKent Overstreet 5631ee608c6SKent Overstreet key_id = request_key("user", key_description, NULL, 5641c6fdbd8SKent Overstreet KEY_SPEC_USER_KEYRING); 5651ee608c6SKent Overstreet if (key_id >= 0) 5661ee608c6SKent Overstreet goto got_key; 5671ee608c6SKent Overstreet 5681ee608c6SKent Overstreet key_id = request_key("user", key_description, NULL, 5691ee608c6SKent Overstreet KEY_SPEC_USER_SESSION_KEYRING); 5701ee608c6SKent Overstreet if (key_id >= 0) 5711ee608c6SKent Overstreet goto got_key; 5721ee608c6SKent Overstreet 5731c6fdbd8SKent Overstreet return -errno; 5741ee608c6SKent Overstreet got_key: 5751c6fdbd8SKent Overstreet 5761c6fdbd8SKent Overstreet if (keyctl_read(key_id, (void *) key, sizeof(*key)) != sizeof(*key)) 5771c6fdbd8SKent Overstreet return -1; 5781c6fdbd8SKent Overstreet 5791c6fdbd8SKent Overstreet return 0; 5801c6fdbd8SKent Overstreet } 5811ee608c6SKent Overstreet 5827b05ecbaSKent Overstreet #include "crypto.h" 5831c6fdbd8SKent Overstreet #endif 5841c6fdbd8SKent Overstreet 58503ea3962SKent Overstreet int bch2_request_key(struct bch_sb *sb, struct bch_key *key) 58603ea3962SKent Overstreet { 587401ec4dbSKent Overstreet struct printbuf key_description = PRINTBUF; 588401ec4dbSKent Overstreet int ret; 58903ea3962SKent Overstreet 590401ec4dbSKent Overstreet prt_printf(&key_description, "bcachefs:"); 591401ec4dbSKent Overstreet pr_uuid(&key_description, sb->user_uuid.b); 59203ea3962SKent Overstreet 593401ec4dbSKent Overstreet ret = __bch2_request_key(key_description.buf, key); 594401ec4dbSKent Overstreet printbuf_exit(&key_description); 5951ee608c6SKent Overstreet 5961ee608c6SKent Overstreet #ifndef __KERNEL__ 5971ee608c6SKent Overstreet if (ret) { 5981ee608c6SKent Overstreet char *passphrase = read_passphrase("Enter passphrase: "); 5991ee608c6SKent Overstreet struct bch_encrypted_key sb_key; 6001ee608c6SKent Overstreet 6011ee608c6SKent Overstreet bch2_passphrase_check(sb, passphrase, 6021ee608c6SKent Overstreet key, &sb_key); 6031ee608c6SKent Overstreet ret = 0; 6041ee608c6SKent Overstreet } 6051ee608c6SKent Overstreet #endif 6061ee608c6SKent Overstreet 6071ee608c6SKent Overstreet /* stash with memfd, pass memfd fd to mount */ 6081ee608c6SKent Overstreet 609401ec4dbSKent Overstreet return ret; 61003ea3962SKent Overstreet } 61103ea3962SKent Overstreet 612793a06d9SKent Overstreet #ifndef __KERNEL__ 613793a06d9SKent Overstreet int bch2_revoke_key(struct bch_sb *sb) 614793a06d9SKent Overstreet { 615793a06d9SKent Overstreet key_serial_t key_id; 616793a06d9SKent Overstreet struct printbuf key_description = PRINTBUF; 617793a06d9SKent Overstreet 618793a06d9SKent Overstreet prt_printf(&key_description, "bcachefs:"); 619793a06d9SKent Overstreet pr_uuid(&key_description, sb->user_uuid.b); 620793a06d9SKent Overstreet 621793a06d9SKent Overstreet key_id = request_key("user", key_description.buf, NULL, KEY_SPEC_USER_KEYRING); 622793a06d9SKent Overstreet printbuf_exit(&key_description); 623793a06d9SKent Overstreet if (key_id < 0) 624793a06d9SKent Overstreet return errno; 625793a06d9SKent Overstreet 626793a06d9SKent Overstreet keyctl_revoke(key_id); 627793a06d9SKent Overstreet 628793a06d9SKent Overstreet return 0; 629793a06d9SKent Overstreet } 630793a06d9SKent Overstreet #endif 631793a06d9SKent Overstreet 6321c6fdbd8SKent Overstreet int bch2_decrypt_sb_key(struct bch_fs *c, 6331c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt, 6341c6fdbd8SKent Overstreet struct bch_key *key) 6351c6fdbd8SKent Overstreet { 6361c6fdbd8SKent Overstreet struct bch_encrypted_key sb_key = crypt->key; 6371c6fdbd8SKent Overstreet struct bch_key user_key; 6381c6fdbd8SKent Overstreet int ret = 0; 6391c6fdbd8SKent Overstreet 6401c6fdbd8SKent Overstreet /* is key encrypted? */ 6411c6fdbd8SKent Overstreet if (!bch2_key_is_encrypted(&sb_key)) 6421c6fdbd8SKent Overstreet goto out; 6431c6fdbd8SKent Overstreet 6441c6fdbd8SKent Overstreet ret = bch2_request_key(c->disk_sb.sb, &user_key); 6451c6fdbd8SKent Overstreet if (ret) { 646d4bf5eecSKent Overstreet bch_err(c, "error requesting encryption key: %s", bch2_err_str(ret)); 6471c6fdbd8SKent Overstreet goto err; 6481c6fdbd8SKent Overstreet } 6491c6fdbd8SKent Overstreet 6501c6fdbd8SKent Overstreet /* decrypt real key: */ 6511c6fdbd8SKent Overstreet ret = bch2_chacha_encrypt_key(&user_key, bch2_sb_key_nonce(c), 6521c6fdbd8SKent Overstreet &sb_key, sizeof(sb_key)); 6531c6fdbd8SKent Overstreet if (ret) 6541c6fdbd8SKent Overstreet goto err; 6551c6fdbd8SKent Overstreet 6561c6fdbd8SKent Overstreet if (bch2_key_is_encrypted(&sb_key)) { 6571c6fdbd8SKent Overstreet bch_err(c, "incorrect encryption key"); 6581c6fdbd8SKent Overstreet ret = -EINVAL; 6591c6fdbd8SKent Overstreet goto err; 6601c6fdbd8SKent Overstreet } 6611c6fdbd8SKent Overstreet out: 6621c6fdbd8SKent Overstreet *key = sb_key.key; 6631c6fdbd8SKent Overstreet err: 6641c6fdbd8SKent Overstreet memzero_explicit(&sb_key, sizeof(sb_key)); 6651c6fdbd8SKent Overstreet memzero_explicit(&user_key, sizeof(user_key)); 6661c6fdbd8SKent Overstreet return ret; 6671c6fdbd8SKent Overstreet } 6681c6fdbd8SKent Overstreet 6691c6fdbd8SKent Overstreet static int bch2_alloc_ciphers(struct bch_fs *c) 6701c6fdbd8SKent Overstreet { 671c06a8b75SKent Overstreet if (c->chacha20) 672c06a8b75SKent Overstreet return 0; 673d4bf5eecSKent Overstreet 674c06a8b75SKent Overstreet struct crypto_sync_skcipher *chacha20 = crypto_alloc_sync_skcipher("chacha20", 0, 0); 675c06a8b75SKent Overstreet int ret = PTR_ERR_OR_ZERO(chacha20); 676d4bf5eecSKent Overstreet if (ret) { 677d4bf5eecSKent Overstreet bch_err(c, "error requesting chacha20 module: %s", bch2_err_str(ret)); 678d4bf5eecSKent Overstreet return ret; 6791c6fdbd8SKent Overstreet } 6801c6fdbd8SKent Overstreet 681c06a8b75SKent Overstreet struct crypto_shash *poly1305 = crypto_alloc_shash("poly1305", 0, 0); 682c06a8b75SKent Overstreet ret = PTR_ERR_OR_ZERO(poly1305); 683d4bf5eecSKent Overstreet if (ret) { 684d4bf5eecSKent Overstreet bch_err(c, "error requesting poly1305 module: %s", bch2_err_str(ret)); 685c06a8b75SKent Overstreet crypto_free_sync_skcipher(chacha20); 686d4bf5eecSKent Overstreet return ret; 6871c6fdbd8SKent Overstreet } 6881c6fdbd8SKent Overstreet 689c06a8b75SKent Overstreet c->chacha20 = chacha20; 690c06a8b75SKent Overstreet c->poly1305 = poly1305; 6911c6fdbd8SKent Overstreet return 0; 6921c6fdbd8SKent Overstreet } 6931c6fdbd8SKent Overstreet 6941c6fdbd8SKent Overstreet int bch2_disable_encryption(struct bch_fs *c) 6951c6fdbd8SKent Overstreet { 6961c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 6971c6fdbd8SKent Overstreet struct bch_key key; 6981c6fdbd8SKent Overstreet int ret = -EINVAL; 6991c6fdbd8SKent Overstreet 7001c6fdbd8SKent Overstreet mutex_lock(&c->sb_lock); 7011c6fdbd8SKent Overstreet 7024637429eSKent Overstreet crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); 7031c6fdbd8SKent Overstreet if (!crypt) 7041c6fdbd8SKent Overstreet goto out; 7051c6fdbd8SKent Overstreet 7061c6fdbd8SKent Overstreet /* is key encrypted? */ 7071c6fdbd8SKent Overstreet ret = 0; 7081c6fdbd8SKent Overstreet if (bch2_key_is_encrypted(&crypt->key)) 7091c6fdbd8SKent Overstreet goto out; 7101c6fdbd8SKent Overstreet 7111c6fdbd8SKent Overstreet ret = bch2_decrypt_sb_key(c, crypt, &key); 7121c6fdbd8SKent Overstreet if (ret) 7131c6fdbd8SKent Overstreet goto out; 7141c6fdbd8SKent Overstreet 71573bd774dSKent Overstreet crypt->key.magic = cpu_to_le64(BCH_KEY_MAGIC); 7161c6fdbd8SKent Overstreet crypt->key.key = key; 7171c6fdbd8SKent Overstreet 7181c6fdbd8SKent Overstreet SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 0); 7191c6fdbd8SKent Overstreet bch2_write_super(c); 7201c6fdbd8SKent Overstreet out: 7211c6fdbd8SKent Overstreet mutex_unlock(&c->sb_lock); 7221c6fdbd8SKent Overstreet 7231c6fdbd8SKent Overstreet return ret; 7241c6fdbd8SKent Overstreet } 7251c6fdbd8SKent Overstreet 7261c6fdbd8SKent Overstreet int bch2_enable_encryption(struct bch_fs *c, bool keyed) 7271c6fdbd8SKent Overstreet { 7281c6fdbd8SKent Overstreet struct bch_encrypted_key key; 7291c6fdbd8SKent Overstreet struct bch_key user_key; 7301c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 7311c6fdbd8SKent Overstreet int ret = -EINVAL; 7321c6fdbd8SKent Overstreet 7331c6fdbd8SKent Overstreet mutex_lock(&c->sb_lock); 7341c6fdbd8SKent Overstreet 7351c6fdbd8SKent Overstreet /* Do we already have an encryption key? */ 7364637429eSKent Overstreet if (bch2_sb_field_get(c->disk_sb.sb, crypt)) 7371c6fdbd8SKent Overstreet goto err; 7381c6fdbd8SKent Overstreet 7391c6fdbd8SKent Overstreet ret = bch2_alloc_ciphers(c); 7401c6fdbd8SKent Overstreet if (ret) 7411c6fdbd8SKent Overstreet goto err; 7421c6fdbd8SKent Overstreet 74373bd774dSKent Overstreet key.magic = cpu_to_le64(BCH_KEY_MAGIC); 7441c6fdbd8SKent Overstreet get_random_bytes(&key.key, sizeof(key.key)); 7451c6fdbd8SKent Overstreet 7461c6fdbd8SKent Overstreet if (keyed) { 7471c6fdbd8SKent Overstreet ret = bch2_request_key(c->disk_sb.sb, &user_key); 7481c6fdbd8SKent Overstreet if (ret) { 749d4bf5eecSKent Overstreet bch_err(c, "error requesting encryption key: %s", bch2_err_str(ret)); 7501c6fdbd8SKent Overstreet goto err; 7511c6fdbd8SKent Overstreet } 7521c6fdbd8SKent Overstreet 7531c6fdbd8SKent Overstreet ret = bch2_chacha_encrypt_key(&user_key, bch2_sb_key_nonce(c), 7541c6fdbd8SKent Overstreet &key, sizeof(key)); 7551c6fdbd8SKent Overstreet if (ret) 7561c6fdbd8SKent Overstreet goto err; 7571c6fdbd8SKent Overstreet } 7581c6fdbd8SKent Overstreet 7591c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&c->chacha20->base, 7601c6fdbd8SKent Overstreet (void *) &key.key, sizeof(key.key)); 7611c6fdbd8SKent Overstreet if (ret) 7621c6fdbd8SKent Overstreet goto err; 7631c6fdbd8SKent Overstreet 7644637429eSKent Overstreet crypt = bch2_sb_field_resize(&c->disk_sb, crypt, 7654637429eSKent Overstreet sizeof(*crypt) / sizeof(u64)); 7661c6fdbd8SKent Overstreet if (!crypt) { 76765d48e35SKent Overstreet ret = -BCH_ERR_ENOSPC_sb_crypt; 7681c6fdbd8SKent Overstreet goto err; 7691c6fdbd8SKent Overstreet } 7701c6fdbd8SKent Overstreet 7711c6fdbd8SKent Overstreet crypt->key = key; 7721c6fdbd8SKent Overstreet 7731c6fdbd8SKent Overstreet /* write superblock */ 7741c6fdbd8SKent Overstreet SET_BCH_SB_ENCRYPTION_TYPE(c->disk_sb.sb, 1); 7751c6fdbd8SKent Overstreet bch2_write_super(c); 7761c6fdbd8SKent Overstreet err: 7771c6fdbd8SKent Overstreet mutex_unlock(&c->sb_lock); 7781c6fdbd8SKent Overstreet memzero_explicit(&user_key, sizeof(user_key)); 7791c6fdbd8SKent Overstreet memzero_explicit(&key, sizeof(key)); 7801c6fdbd8SKent Overstreet return ret; 7811c6fdbd8SKent Overstreet } 7821c6fdbd8SKent Overstreet 7831c6fdbd8SKent Overstreet void bch2_fs_encryption_exit(struct bch_fs *c) 7841c6fdbd8SKent Overstreet { 785c06a8b75SKent Overstreet if (c->poly1305) 7861c6fdbd8SKent Overstreet crypto_free_shash(c->poly1305); 787c06a8b75SKent Overstreet if (c->chacha20) 7881c6fdbd8SKent Overstreet crypto_free_sync_skcipher(c->chacha20); 789c06a8b75SKent Overstreet if (c->sha256) 7901c6fdbd8SKent Overstreet crypto_free_shash(c->sha256); 7911c6fdbd8SKent Overstreet } 7921c6fdbd8SKent Overstreet 7931c6fdbd8SKent Overstreet int bch2_fs_encryption_init(struct bch_fs *c) 7941c6fdbd8SKent Overstreet { 7951c6fdbd8SKent Overstreet struct bch_sb_field_crypt *crypt; 7961c6fdbd8SKent Overstreet struct bch_key key; 7971c6fdbd8SKent Overstreet int ret = 0; 7981c6fdbd8SKent Overstreet 7991c6fdbd8SKent Overstreet c->sha256 = crypto_alloc_shash("sha256", 0, 0); 800d4bf5eecSKent Overstreet ret = PTR_ERR_OR_ZERO(c->sha256); 801d4bf5eecSKent Overstreet if (ret) { 802c06a8b75SKent Overstreet c->sha256 = NULL; 803d4bf5eecSKent Overstreet bch_err(c, "error requesting sha256 module: %s", bch2_err_str(ret)); 8041c6fdbd8SKent Overstreet goto out; 8051c6fdbd8SKent Overstreet } 8061c6fdbd8SKent Overstreet 8074637429eSKent Overstreet crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); 8081c6fdbd8SKent Overstreet if (!crypt) 8091c6fdbd8SKent Overstreet goto out; 8101c6fdbd8SKent Overstreet 8111c6fdbd8SKent Overstreet ret = bch2_alloc_ciphers(c); 8121c6fdbd8SKent Overstreet if (ret) 8131c6fdbd8SKent Overstreet goto out; 8141c6fdbd8SKent Overstreet 8151c6fdbd8SKent Overstreet ret = bch2_decrypt_sb_key(c, crypt, &key); 8161c6fdbd8SKent Overstreet if (ret) 8171c6fdbd8SKent Overstreet goto out; 8181c6fdbd8SKent Overstreet 8191c6fdbd8SKent Overstreet ret = crypto_skcipher_setkey(&c->chacha20->base, 8201c6fdbd8SKent Overstreet (void *) &key.key, sizeof(key.key)); 8211c6fdbd8SKent Overstreet if (ret) 8221c6fdbd8SKent Overstreet goto out; 8231c6fdbd8SKent Overstreet out: 8241c6fdbd8SKent Overstreet memzero_explicit(&key, sizeof(key)); 8251c6fdbd8SKent Overstreet return ret; 8261c6fdbd8SKent Overstreet } 827