// SPDX-License-Identifier: GPL-2.0-or-later /* Large capacity key type * * Copyright (C) 2017-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
/* * If the data is under this limit, there's no point creating a shm file to * hold it as the permanently resident metadata for the shmem fs will be at * least as large as the data.
*/ #define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))
/* * big_key defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload
*/ struct key_type key_type_big_key = {
.name = "big_key",
.preparse = big_key_preparse,
.free_preparse = big_key_free_preparse,
.instantiate = generic_key_instantiate,
.revoke = big_key_revoke,
.destroy = big_key_destroy,
.describe = big_key_describe,
.read = big_key_read,
.update = big_key_update,
};
/* * Preparse a big key
*/ int big_key_preparse(struct key_preparsed_payload *prep)
{ struct big_key_payload *payload = to_big_key_payload(prep->payload); struct file *file;
u8 *buf, *enckey;
ssize_t written;
size_t datalen = prep->datalen;
size_t enclen = datalen + CHACHA20POLY1305_AUTHTAG_SIZE; int ret;
if (datalen > BIG_KEY_FILE_THRESHOLD) { /* Create a shmem file to store the data in. This will permit the data * to be swapped out if needed. * * File content is stored encrypted with randomly generated key. * Since the key is random for each file, we can set the nonce * to zero, provided we never define a ->update() call.
*/
loff_t pos = 0;
buf = kvmalloc(enclen, GFP_KERNEL); if (!buf) return -ENOMEM;
/* generate random key */
enckey = kmalloc(CHACHA20POLY1305_KEY_SIZE, GFP_KERNEL); if (!enckey) {
ret = -ENOMEM; goto error;
}
ret = get_random_bytes_wait(enckey, CHACHA20POLY1305_KEY_SIZE); if (unlikely(ret)) goto err_enckey;
/* save aligned data to file */
file = shmem_kernel_file_setup("", enclen, 0); if (IS_ERR(file)) {
ret = PTR_ERR(file); goto err_enckey;
}
written = kernel_write(file, buf, enclen, &pos); if (written != enclen) {
ret = written; if (written >= 0)
ret = -EIO; goto err_fput;
}
/* Pin the mount and dentry to the key so that we can open it again * later
*/
payload->data = enckey;
payload->path = file->f_path;
path_get(&payload->path);
fput(file);
kvfree_sensitive(buf, enclen);
} else { /* Just store the data in a buffer */ void *data = kmalloc(datalen, GFP_KERNEL);
if (prep->datalen > BIG_KEY_FILE_THRESHOLD)
path_put(&payload->path);
kfree_sensitive(payload->data);
}
/* * dispose of the links from a revoked keyring * - called with the key sem write-locked
*/ void big_key_revoke(struct key *key)
{ struct big_key_payload *payload = to_big_key_payload(key->payload);
/* clear the quota */
key_payload_reserve(key, 0); if (key_is_positive(key) && payload->length > BIG_KEY_FILE_THRESHOLD)
vfs_truncate(&payload->path, 0);
}
/* * dispose of the data dangling from the corpse of a big_key key
*/ void big_key_destroy(struct key *key)
{ struct big_key_payload *payload = to_big_key_payload(key->payload);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.