Whamcloud - gitweb
LU-12275 sec: add llcrypt as file encryption library
[fs/lustre-release.git] / libcfs / libcfs / crypto / bio.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * This contains encryption functions for per-file encryption.
4  *
5  * Copyright (C) 2015, Google, Inc.
6  * Copyright (C) 2015, Motorola Mobility
7  *
8  * Written by Michael Halcrow, 2014.
9  *
10  * Filename encryption additions
11  *      Uday Savagaonkar, 2014
12  * Encryption policy handling additions
13  *      Ildar Muslukhov, 2014
14  * Add llcrypt_pullback_bio_page()
15  *      Jaegeuk Kim, 2015.
16  *
17  * This has not yet undergone a rigorous security audit.
18  *
19  * The usage of AES-XTS should conform to recommendations in NIST
20  * Special Publication 800-38E and IEEE P1619/D16.
21  */
22 /*
23  * Linux commit 219d54332a09
24  * tags/v5.4
25  */
26
27 #include <linux/pagemap.h>
28 #include <linux/module.h>
29 #include <linux/bio.h>
30 #include <linux/namei.h>
31 #include "llcrypt_private.h"
32
33 static void __llcrypt_decrypt_bio(struct bio *bio, bool done)
34 {
35         struct bio_vec *bv;
36 #ifdef HAVE_BVEC_ITER_ALL
37         struct bvec_iter_all iter_all;
38 #else
39         int iter_all;
40 #endif
41
42         bio_for_each_segment_all(bv, bio, iter_all) {
43                 struct page *page = bv->bv_page;
44                 int ret = llcrypt_decrypt_pagecache_blocks(page, bv->bv_len,
45                                                            bv->bv_offset);
46                 if (ret)
47                         SetPageError(page);
48                 else if (done)
49                         SetPageUptodate(page);
50                 if (done)
51                         unlock_page(page);
52         }
53 }
54
55 void llcrypt_decrypt_bio(struct bio *bio)
56 {
57         __llcrypt_decrypt_bio(bio, false);
58 }
59 EXPORT_SYMBOL(llcrypt_decrypt_bio);
60
61 static void completion_pages(struct work_struct *work)
62 {
63         struct llcrypt_ctx *ctx = container_of(work, struct llcrypt_ctx, work);
64         struct bio *bio = ctx->bio;
65
66         __llcrypt_decrypt_bio(bio, true);
67         llcrypt_release_ctx(ctx);
68         bio_put(bio);
69 }
70
71 void llcrypt_enqueue_decrypt_bio(struct llcrypt_ctx *ctx, struct bio *bio)
72 {
73         INIT_WORK(&ctx->work, completion_pages);
74         ctx->bio = bio;
75         llcrypt_enqueue_decrypt_work(&ctx->work);
76 }
77 EXPORT_SYMBOL(llcrypt_enqueue_decrypt_bio);
78
79 int llcrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
80                                 sector_t pblk, unsigned int len)
81 {
82         const unsigned int blockbits = inode->i_blkbits;
83         const unsigned int blocksize = 1 << blockbits;
84         struct page *ciphertext_page;
85         struct bio *bio;
86         int ret, err = 0;
87
88         ciphertext_page = llcrypt_alloc_bounce_page(GFP_NOWAIT);
89         if (!ciphertext_page)
90                 return -ENOMEM;
91
92         while (len--) {
93                 err = llcrypt_crypt_block(inode, FS_ENCRYPT, lblk,
94                                           ZERO_PAGE(0), ciphertext_page,
95                                           blocksize, 0, GFP_NOFS);
96                 if (err)
97                         goto errout;
98
99                 bio = bio_alloc(GFP_NOWAIT, 1);
100                 if (!bio) {
101                         err = -ENOMEM;
102                         goto errout;
103                 }
104                 bio_set_dev(bio, inode->i_sb->s_bdev);
105                 bio->bi_iter.bi_sector = pblk << (blockbits - 9);
106                 bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
107                 ret = bio_add_page(bio, ciphertext_page, blocksize, 0);
108                 if (WARN_ON(ret != blocksize)) {
109                         /* should never happen! */
110                         bio_put(bio);
111                         err = -EIO;
112                         goto errout;
113                 }
114                 err = submit_bio_wait(bio);
115                 if (err == 0 && bio->bi_status)
116                         err = -EIO;
117                 bio_put(bio);
118                 if (err)
119                         goto errout;
120                 lblk++;
121                 pblk++;
122         }
123         err = 0;
124 errout:
125         llcrypt_free_bounce_page(ciphertext_page);
126         return err;
127 }
128 EXPORT_SYMBOL(llcrypt_zeroout_range);