^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Large capacity key type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2017-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Written by David Howells (dhowells@redhat.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define pr_fmt(fmt) "big_key: "fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/shmem_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/random.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <keys/user-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <keys/big_key-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <crypto/chacha20poly1305.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Layout of key payload words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) big_key_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) big_key_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) big_key_path_2nd_part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) big_key_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * If the data is under this limit, there's no point creating a shm file to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * hold it as the permanently resident metadata for the shmem fs will be at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * least as large as the data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * big_key defined keys take an arbitrary string as the description and an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * arbitrary blob of data as the payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct key_type key_type_big_key = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .name = "big_key",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .preparse = big_key_preparse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .free_preparse = big_key_free_preparse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .instantiate = generic_key_instantiate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .revoke = big_key_revoke,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .destroy = big_key_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .describe = big_key_describe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .read = big_key_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .update = big_key_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * Preparse a big key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int big_key_preparse(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct path *path = (struct path *)&prep->payload.data[big_key_path];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 *buf, *enckey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ssize_t written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) size_t datalen = prep->datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) size_t enclen = datalen + CHACHA20POLY1305_AUTHTAG_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Set an arbitrary quota */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) prep->quotalen = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (datalen > BIG_KEY_FILE_THRESHOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Create a shmem file to store the data in. This will permit the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * to be swapped out if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * File content is stored encrypted with randomly generated key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Since the key is random for each file, we can set the nonce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * to zero, provided we never define a ->update() call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) loff_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) buf = kvmalloc(enclen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* generate random key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) enckey = kmalloc(CHACHA20POLY1305_KEY_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!enckey) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ret = get_random_bytes_wait(enckey, CHACHA20POLY1305_KEY_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) goto err_enckey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* encrypt data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) chacha20poly1305_encrypt(buf, prep->data, datalen, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 0, enckey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* save aligned data to file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) file = shmem_kernel_file_setup("", enclen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (IS_ERR(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ret = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto err_enckey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) written = kernel_write(file, buf, enclen, &pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (written != enclen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ret = written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (written >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) goto err_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Pin the mount and dentry to the key so that we can open it again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) prep->payload.data[big_key_data] = enckey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *path = file->f_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) path_get(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) memzero_explicit(buf, enclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) kvfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Just store the data in a buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void *data = kmalloc(datalen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) prep->payload.data[big_key_data] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) memcpy(data, prep->data, prep->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) err_fput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err_enckey:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) kfree_sensitive(enckey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) memzero_explicit(buf, enclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) kvfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Clear preparsement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void big_key_free_preparse(struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct path *path = (struct path *)&prep->payload.data[big_key_path];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) path_put(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) kfree_sensitive(prep->payload.data[big_key_data]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * dispose of the links from a revoked keyring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * - called with the key sem write-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) void big_key_revoke(struct key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct path *path = (struct path *)&key->payload.data[big_key_path];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* clear the quota */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) key_payload_reserve(key, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (key_is_positive(key) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) vfs_truncate(path, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * dispose of the data dangling from the corpse of a big_key key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) void big_key_destroy(struct key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) size_t datalen = (size_t)key->payload.data[big_key_len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (datalen > BIG_KEY_FILE_THRESHOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct path *path = (struct path *)&key->payload.data[big_key_path];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) path_put(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) path->mnt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) path->dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) kfree_sensitive(key->payload.data[big_key_data]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) key->payload.data[big_key_data] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * Update a big key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int big_key_update(struct key *key, struct key_preparsed_payload *prep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = key_payload_reserve(key, prep->datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (key_is_positive(key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) big_key_destroy(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return generic_key_instantiate(key, prep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * describe the big_key key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) void big_key_describe(const struct key *key, struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) size_t datalen = (size_t)key->payload.data[big_key_len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) seq_puts(m, key->description);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (key_is_positive(key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) seq_printf(m, ": %zu [%s]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) datalen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * read the key data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * - the key's semaphore is read-locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) long big_key_read(const struct key *key, char *buffer, size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) size_t datalen = (size_t)key->payload.data[big_key_len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (!buffer || buflen < datalen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (datalen > BIG_KEY_FILE_THRESHOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct path *path = (struct path *)&key->payload.data[big_key_path];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) u8 *buf, *enckey = (u8 *)key->payload.data[big_key_data];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) size_t enclen = datalen + CHACHA20POLY1305_AUTHTAG_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) loff_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) buf = kvmalloc(enclen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) file = dentry_open(path, O_RDONLY, current_cred());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (IS_ERR(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* read file to kernel and decrypt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ret = kernel_read(file, buf, enclen, &pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (ret != enclen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto err_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = chacha20poly1305_decrypt(buf, buf, enclen, NULL, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) enckey) ? 0 : -EBADMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) goto err_fput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ret = datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* copy out decrypted data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) memcpy(buffer, buf, datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) err_fput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) memzero_explicit(buf, enclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) kvfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ret = datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) memcpy(buffer, key->payload.data[big_key_data], datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * Register key type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int __init big_key_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return register_key_type(&key_type_big_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) late_initcall(big_key_init);