Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);