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