Blame view

security/keys/big_key.c 10.1 KB
b4d0d230c   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
ab3c3587f   David Howells   KEYS: Implement a...
2
3
  /* Large capacity key type
   *
428490e38   Jason A. Donenfeld   security/keys: re...
4
   * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
ab3c3587f   David Howells   KEYS: Implement a...
5
6
   * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
ab3c3587f   David Howells   KEYS: Implement a...
7
   */
7df3e59c3   David Howells   KEYS: Sort out bi...
8
  #define pr_fmt(fmt) "big_key: "fmt
ab3c3587f   David Howells   KEYS: Implement a...
9
10
11
12
13
  #include <linux/init.h>
  #include <linux/seq_file.h>
  #include <linux/file.h>
  #include <linux/shmem_fs.h>
  #include <linux/err.h>
13100a72f   Kirill Marinushkin   Security: Keys: B...
14
  #include <linux/scatterlist.h>
428490e38   Jason A. Donenfeld   security/keys: re...
15
  #include <linux/random.h>
514c60324   Randy Dunlap   headers: untangle...
16
  #include <linux/vmalloc.h>
ab3c3587f   David Howells   KEYS: Implement a...
17
18
  #include <keys/user-type.h>
  #include <keys/big_key-type.h>
428490e38   Jason A. Donenfeld   security/keys: re...
19
  #include <crypto/aead.h>
a964f3956   Tycho Andersen   big key: get rid ...
20
  #include <crypto/gcm.h>
ab3c3587f   David Howells   KEYS: Implement a...
21

d9f4bb1a0   David Howells   KEYS: Use individ...
22
23
24
25
26
27
  struct big_key_buf {
  	unsigned int		nr_pages;
  	void			*virt;
  	struct scatterlist	*sg;
  	struct page		*pages[];
  };
ab3c3587f   David Howells   KEYS: Implement a...
28
  /*
146aa8b14   David Howells   KEYS: Merge the t...
29
30
31
32
33
34
35
36
37
38
   * Layout of key payload words.
   */
  enum {
  	big_key_data,
  	big_key_path,
  	big_key_path_2nd_part,
  	big_key_len,
  };
  
  /*
13100a72f   Kirill Marinushkin   Security: Keys: B...
39
40
41
42
43
44
45
46
   * Crypto operation with big_key data
   */
  enum big_key_op {
  	BIG_KEY_ENC,
  	BIG_KEY_DEC,
  };
  
  /*
ab3c3587f   David Howells   KEYS: Implement a...
47
48
49
50
51
52
53
   * 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))
  
  /*
13100a72f   Kirill Marinushkin   Security: Keys: B...
54
55
   * Key size for big_key data encryption
   */
428490e38   Jason A. Donenfeld   security/keys: re...
56
57
58
59
60
61
  #define ENC_KEY_SIZE 32
  
  /*
   * Authentication tag length
   */
  #define ENC_AUTHTAG_SIZE 16
13100a72f   Kirill Marinushkin   Security: Keys: B...
62
63
  
  /*
ab3c3587f   David Howells   KEYS: Implement a...
64
65
66
67
68
   * 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",
002edaf76   David Howells   KEYS: big_key: Us...
69
70
71
  	.preparse		= big_key_preparse,
  	.free_preparse		= big_key_free_preparse,
  	.instantiate		= generic_key_instantiate,
ab3c3587f   David Howells   KEYS: Implement a...
72
73
74
75
  	.revoke			= big_key_revoke,
  	.destroy		= big_key_destroy,
  	.describe		= big_key_describe,
  	.read			= big_key_read,
428490e38   Jason A. Donenfeld   security/keys: re...
76
  	/* no ->update(); don't add it without changing big_key_crypt() nonce */
ab3c3587f   David Howells   KEYS: Implement a...
77
78
79
  };
  
  /*
428490e38   Jason A. Donenfeld   security/keys: re...
80
   * Crypto names for big_key data authenticated encryption
13100a72f   Kirill Marinushkin   Security: Keys: B...
81
   */
428490e38   Jason A. Donenfeld   security/keys: re...
82
  static const char big_key_alg_name[] = "gcm(aes)";
a964f3956   Tycho Andersen   big key: get rid ...
83
  #define BIG_KEY_IV_SIZE		GCM_AES_IV_SIZE
13100a72f   Kirill Marinushkin   Security: Keys: B...
84
85
  
  /*
428490e38   Jason A. Donenfeld   security/keys: re...
86
   * Crypto algorithms for big_key data authenticated encryption
13100a72f   Kirill Marinushkin   Security: Keys: B...
87
   */
428490e38   Jason A. Donenfeld   security/keys: re...
88
  static struct crypto_aead *big_key_aead;
13100a72f   Kirill Marinushkin   Security: Keys: B...
89
90
  
  /*
428490e38   Jason A. Donenfeld   security/keys: re...
91
   * Since changing the key affects the entire object, we need a mutex.
13100a72f   Kirill Marinushkin   Security: Keys: B...
92
   */
428490e38   Jason A. Donenfeld   security/keys: re...
93
  static DEFINE_MUTEX(big_key_aead_lock);
13100a72f   Kirill Marinushkin   Security: Keys: B...
94
95
96
97
  
  /*
   * Encrypt/decrypt big_key data
   */
d9f4bb1a0   David Howells   KEYS: Use individ...
98
  static int big_key_crypt(enum big_key_op op, struct big_key_buf *buf, size_t datalen, u8 *key)
13100a72f   Kirill Marinushkin   Security: Keys: B...
99
  {
428490e38   Jason A. Donenfeld   security/keys: re...
100
  	int ret;
428490e38   Jason A. Donenfeld   security/keys: re...
101
102
103
104
105
106
107
  	struct aead_request *aead_req;
  	/* We always use a zero nonce. The reason we can get away with this is
  	 * because we're using a different randomly generated key for every
  	 * different encryption. Notably, too, key_type_big_key doesn't define
  	 * an .update function, so there's no chance we'll wind up reusing the
  	 * key to encrypt updated data. Simply put: one key, one encryption.
  	 */
a964f3956   Tycho Andersen   big key: get rid ...
108
  	u8 zero_nonce[BIG_KEY_IV_SIZE];
428490e38   Jason A. Donenfeld   security/keys: re...
109
110
111
112
113
114
  
  	aead_req = aead_request_alloc(big_key_aead, GFP_KERNEL);
  	if (!aead_req)
  		return -ENOMEM;
  
  	memset(zero_nonce, 0, sizeof(zero_nonce));
d9f4bb1a0   David Howells   KEYS: Use individ...
115
  	aead_request_set_crypt(aead_req, buf->sg, buf->sg, datalen, zero_nonce);
428490e38   Jason A. Donenfeld   security/keys: re...
116
117
118
119
120
  	aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
  	aead_request_set_ad(aead_req, 0);
  
  	mutex_lock(&big_key_aead_lock);
  	if (crypto_aead_setkey(big_key_aead, key, ENC_KEY_SIZE)) {
13100a72f   Kirill Marinushkin   Security: Keys: B...
121
122
123
  		ret = -EAGAIN;
  		goto error;
  	}
13100a72f   Kirill Marinushkin   Security: Keys: B...
124
  	if (op == BIG_KEY_ENC)
428490e38   Jason A. Donenfeld   security/keys: re...
125
  		ret = crypto_aead_encrypt(aead_req);
13100a72f   Kirill Marinushkin   Security: Keys: B...
126
  	else
428490e38   Jason A. Donenfeld   security/keys: re...
127
  		ret = crypto_aead_decrypt(aead_req);
13100a72f   Kirill Marinushkin   Security: Keys: B...
128
  error:
428490e38   Jason A. Donenfeld   security/keys: re...
129
130
  	mutex_unlock(&big_key_aead_lock);
  	aead_request_free(aead_req);
13100a72f   Kirill Marinushkin   Security: Keys: B...
131
132
133
134
  	return ret;
  }
  
  /*
d9f4bb1a0   David Howells   KEYS: Use individ...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
   * Free up the buffer.
   */
  static void big_key_free_buffer(struct big_key_buf *buf)
  {
  	unsigned int i;
  
  	if (buf->virt) {
  		memset(buf->virt, 0, buf->nr_pages * PAGE_SIZE);
  		vunmap(buf->virt);
  	}
  
  	for (i = 0; i < buf->nr_pages; i++)
  		if (buf->pages[i])
  			__free_page(buf->pages[i]);
  
  	kfree(buf);
  }
  
  /*
   * Allocate a buffer consisting of a set of pages with a virtual mapping
   * applied over them.
   */
  static void *big_key_alloc_buffer(size_t len)
  {
  	struct big_key_buf *buf;
  	unsigned int npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
  	unsigned int i, l;
  
  	buf = kzalloc(sizeof(struct big_key_buf) +
  		      sizeof(struct page) * npg +
  		      sizeof(struct scatterlist) * npg,
  		      GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->nr_pages = npg;
  	buf->sg = (void *)(buf->pages + npg);
  	sg_init_table(buf->sg, npg);
  
  	for (i = 0; i < buf->nr_pages; i++) {
  		buf->pages[i] = alloc_page(GFP_KERNEL);
  		if (!buf->pages[i])
  			goto nomem;
  
  		l = min_t(size_t, len, PAGE_SIZE);
  		sg_set_page(&buf->sg[i], buf->pages[i], l, 0);
  		len -= l;
  	}
  
  	buf->virt = vmap(buf->pages, buf->nr_pages, VM_MAP, PAGE_KERNEL);
  	if (!buf->virt)
  		goto nomem;
  
  	return buf;
  
  nomem:
  	big_key_free_buffer(buf);
  	return NULL;
  }
  
  /*
002edaf76   David Howells   KEYS: big_key: Us...
196
   * Preparse a big key
ab3c3587f   David Howells   KEYS: Implement a...
197
   */
002edaf76   David Howells   KEYS: big_key: Us...
198
  int big_key_preparse(struct key_preparsed_payload *prep)
ab3c3587f   David Howells   KEYS: Implement a...
199
  {
d9f4bb1a0   David Howells   KEYS: Use individ...
200
  	struct big_key_buf *buf;
146aa8b14   David Howells   KEYS: Merge the t...
201
  	struct path *path = (struct path *)&prep->payload.data[big_key_path];
ab3c3587f   David Howells   KEYS: Implement a...
202
  	struct file *file;
13100a72f   Kirill Marinushkin   Security: Keys: B...
203
  	u8 *enckey;
ab3c3587f   David Howells   KEYS: Implement a...
204
  	ssize_t written;
d9f4bb1a0   David Howells   KEYS: Use individ...
205
  	size_t datalen = prep->datalen, enclen = datalen + ENC_AUTHTAG_SIZE;
ab3c3587f   David Howells   KEYS: Implement a...
206
  	int ret;
ab3c3587f   David Howells   KEYS: Implement a...
207
  	if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
d9f4bb1a0   David Howells   KEYS: Use individ...
208
  		return -EINVAL;
ab3c3587f   David Howells   KEYS: Implement a...
209
210
  
  	/* Set an arbitrary quota */
002edaf76   David Howells   KEYS: big_key: Us...
211
  	prep->quotalen = 16;
ab3c3587f   David Howells   KEYS: Implement a...
212

146aa8b14   David Howells   KEYS: Merge the t...
213
  	prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
ab3c3587f   David Howells   KEYS: Implement a...
214
215
216
217
218
  
  	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.
  		 *
13100a72f   Kirill Marinushkin   Security: Keys: B...
219
  		 * File content is stored encrypted with randomly generated key.
ab3c3587f   David Howells   KEYS: Implement a...
220
  		 */
e13ec939e   Christoph Hellwig   fs: fix kernel_wr...
221
  		loff_t pos = 0;
13100a72f   Kirill Marinushkin   Security: Keys: B...
222

d9f4bb1a0   David Howells   KEYS: Use individ...
223
224
  		buf = big_key_alloc_buffer(enclen);
  		if (!buf)
13100a72f   Kirill Marinushkin   Security: Keys: B...
225
  			return -ENOMEM;
d9f4bb1a0   David Howells   KEYS: Use individ...
226
  		memcpy(buf->virt, prep->data, datalen);
13100a72f   Kirill Marinushkin   Security: Keys: B...
227
228
229
230
231
232
233
  
  		/* generate random key */
  		enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
  		if (!enckey) {
  			ret = -ENOMEM;
  			goto error;
  		}
428490e38   Jason A. Donenfeld   security/keys: re...
234
235
  		ret = get_random_bytes_wait(enckey, ENC_KEY_SIZE);
  		if (unlikely(ret))
13100a72f   Kirill Marinushkin   Security: Keys: B...
236
237
238
  			goto err_enckey;
  
  		/* encrypt aligned data */
d9f4bb1a0   David Howells   KEYS: Use individ...
239
  		ret = big_key_crypt(BIG_KEY_ENC, buf, datalen, enckey);
13100a72f   Kirill Marinushkin   Security: Keys: B...
240
241
242
243
244
  		if (ret)
  			goto err_enckey;
  
  		/* save aligned data to file */
  		file = shmem_kernel_file_setup("", enclen, 0);
d2b869702   Wei Yongjun   KEYS: fix error r...
245
246
  		if (IS_ERR(file)) {
  			ret = PTR_ERR(file);
13100a72f   Kirill Marinushkin   Security: Keys: B...
247
  			goto err_enckey;
d2b869702   Wei Yongjun   KEYS: fix error r...
248
  		}
ab3c3587f   David Howells   KEYS: Implement a...
249

d9f4bb1a0   David Howells   KEYS: Use individ...
250
  		written = kernel_write(file, buf->virt, enclen, &pos);
13100a72f   Kirill Marinushkin   Security: Keys: B...
251
  		if (written != enclen) {
97826c821   David Howells   KEYS: Fix error h...
252
  			ret = written;
ab3c3587f   David Howells   KEYS: Implement a...
253
254
255
256
257
258
259
260
  			if (written >= 0)
  				ret = -ENOMEM;
  			goto err_fput;
  		}
  
  		/* Pin the mount and dentry to the key so that we can open it again
  		 * later
  		 */
13100a72f   Kirill Marinushkin   Security: Keys: B...
261
  		prep->payload.data[big_key_data] = enckey;
ab3c3587f   David Howells   KEYS: Implement a...
262
263
264
  		*path = file->f_path;
  		path_get(path);
  		fput(file);
d9f4bb1a0   David Howells   KEYS: Use individ...
265
  		big_key_free_buffer(buf);
ab3c3587f   David Howells   KEYS: Implement a...
266
267
268
  	} else {
  		/* Just store the data in a buffer */
  		void *data = kmalloc(datalen, GFP_KERNEL);
13100a72f   Kirill Marinushkin   Security: Keys: B...
269

002edaf76   David Howells   KEYS: big_key: Us...
270
271
  		if (!data)
  			return -ENOMEM;
ab3c3587f   David Howells   KEYS: Implement a...
272

146aa8b14   David Howells   KEYS: Merge the t...
273
274
  		prep->payload.data[big_key_data] = data;
  		memcpy(data, prep->data, prep->datalen);
ab3c3587f   David Howells   KEYS: Implement a...
275
276
277
278
279
  	}
  	return 0;
  
  err_fput:
  	fput(file);
13100a72f   Kirill Marinushkin   Security: Keys: B...
280
  err_enckey:
910801809   Jason A. Donenfeld   security/keys: pr...
281
  	kzfree(enckey);
ab3c3587f   David Howells   KEYS: Implement a...
282
  error:
d9f4bb1a0   David Howells   KEYS: Use individ...
283
  	big_key_free_buffer(buf);
ab3c3587f   David Howells   KEYS: Implement a...
284
285
286
287
  	return ret;
  }
  
  /*
002edaf76   David Howells   KEYS: big_key: Us...
288
289
290
291
292
   * Clear preparsement.
   */
  void big_key_free_preparse(struct key_preparsed_payload *prep)
  {
  	if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
146aa8b14   David Howells   KEYS: Merge the t...
293
  		struct path *path = (struct path *)&prep->payload.data[big_key_path];
13100a72f   Kirill Marinushkin   Security: Keys: B...
294

002edaf76   David Howells   KEYS: big_key: Us...
295
  		path_put(path);
002edaf76   David Howells   KEYS: big_key: Us...
296
  	}
910801809   Jason A. Donenfeld   security/keys: pr...
297
  	kzfree(prep->payload.data[big_key_data]);
002edaf76   David Howells   KEYS: big_key: Us...
298
299
300
  }
  
  /*
ab3c3587f   David Howells   KEYS: Implement a...
301
302
303
304
305
   * dispose of the links from a revoked keyring
   * - called with the key sem write-locked
   */
  void big_key_revoke(struct key *key)
  {
146aa8b14   David Howells   KEYS: Merge the t...
306
  	struct path *path = (struct path *)&key->payload.data[big_key_path];
ab3c3587f   David Howells   KEYS: Implement a...
307
308
309
  
  	/* clear the quota */
  	key_payload_reserve(key, 0);
363b02dab   David Howells   KEYS: Fix race be...
310
  	if (key_is_positive(key) &&
146aa8b14   David Howells   KEYS: Merge the t...
311
  	    (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
ab3c3587f   David Howells   KEYS: Implement a...
312
313
314
315
316
317
318
319
  		vfs_truncate(path, 0);
  }
  
  /*
   * dispose of the data dangling from the corpse of a big_key key
   */
  void big_key_destroy(struct key *key)
  {
146aa8b14   David Howells   KEYS: Merge the t...
320
  	size_t datalen = (size_t)key->payload.data[big_key_len];
13100a72f   Kirill Marinushkin   Security: Keys: B...
321
  	if (datalen > BIG_KEY_FILE_THRESHOLD) {
146aa8b14   David Howells   KEYS: Merge the t...
322
  		struct path *path = (struct path *)&key->payload.data[big_key_path];
13100a72f   Kirill Marinushkin   Security: Keys: B...
323

ab3c3587f   David Howells   KEYS: Implement a...
324
325
326
  		path_put(path);
  		path->mnt = NULL;
  		path->dentry = NULL;
ab3c3587f   David Howells   KEYS: Implement a...
327
  	}
910801809   Jason A. Donenfeld   security/keys: pr...
328
  	kzfree(key->payload.data[big_key_data]);
13100a72f   Kirill Marinushkin   Security: Keys: B...
329
  	key->payload.data[big_key_data] = NULL;
ab3c3587f   David Howells   KEYS: Implement a...
330
331
332
333
334
335
336
  }
  
  /*
   * describe the big_key key
   */
  void big_key_describe(const struct key *key, struct seq_file *m)
  {
146aa8b14   David Howells   KEYS: Merge the t...
337
  	size_t datalen = (size_t)key->payload.data[big_key_len];
ab3c3587f   David Howells   KEYS: Implement a...
338
339
  
  	seq_puts(m, key->description);
363b02dab   David Howells   KEYS: Fix race be...
340
  	if (key_is_positive(key))
146aa8b14   David Howells   KEYS: Merge the t...
341
  		seq_printf(m, ": %zu [%s]",
ab3c3587f   David Howells   KEYS: Implement a...
342
343
344
345
346
347
348
349
350
351
  			   datalen,
  			   datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
  }
  
  /*
   * read the key data
   * - the key's semaphore is read-locked
   */
  long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
  {
146aa8b14   David Howells   KEYS: Merge the t...
352
  	size_t datalen = (size_t)key->payload.data[big_key_len];
ab3c3587f   David Howells   KEYS: Implement a...
353
354
355
356
357
358
  	long ret;
  
  	if (!buffer || buflen < datalen)
  		return datalen;
  
  	if (datalen > BIG_KEY_FILE_THRESHOLD) {
d9f4bb1a0   David Howells   KEYS: Use individ...
359
  		struct big_key_buf *buf;
146aa8b14   David Howells   KEYS: Merge the t...
360
  		struct path *path = (struct path *)&key->payload.data[big_key_path];
ab3c3587f   David Howells   KEYS: Implement a...
361
  		struct file *file;
13100a72f   Kirill Marinushkin   Security: Keys: B...
362
  		u8 *enckey = (u8 *)key->payload.data[big_key_data];
428490e38   Jason A. Donenfeld   security/keys: re...
363
  		size_t enclen = datalen + ENC_AUTHTAG_SIZE;
bdd1d2d3d   Christoph Hellwig   fs: fix kernel_re...
364
  		loff_t pos = 0;
13100a72f   Kirill Marinushkin   Security: Keys: B...
365

d9f4bb1a0   David Howells   KEYS: Use individ...
366
367
  		buf = big_key_alloc_buffer(enclen);
  		if (!buf)
13100a72f   Kirill Marinushkin   Security: Keys: B...
368
  			return -ENOMEM;
ab3c3587f   David Howells   KEYS: Implement a...
369
370
  
  		file = dentry_open(path, O_RDONLY, current_cred());
13100a72f   Kirill Marinushkin   Security: Keys: B...
371
372
373
374
  		if (IS_ERR(file)) {
  			ret = PTR_ERR(file);
  			goto error;
  		}
ab3c3587f   David Howells   KEYS: Implement a...
375

13100a72f   Kirill Marinushkin   Security: Keys: B...
376
  		/* read file to kernel and decrypt */
d9f4bb1a0   David Howells   KEYS: Use individ...
377
  		ret = kernel_read(file, buf->virt, enclen, &pos);
13100a72f   Kirill Marinushkin   Security: Keys: B...
378
  		if (ret >= 0 && ret != enclen) {
ab3c3587f   David Howells   KEYS: Implement a...
379
  			ret = -EIO;
13100a72f   Kirill Marinushkin   Security: Keys: B...
380
381
  			goto err_fput;
  		}
d9f4bb1a0   David Howells   KEYS: Use individ...
382
  		ret = big_key_crypt(BIG_KEY_DEC, buf, enclen, enckey);
13100a72f   Kirill Marinushkin   Security: Keys: B...
383
384
385
386
387
388
  		if (ret)
  			goto err_fput;
  
  		ret = datalen;
  
  		/* copy decrypted data to user */
d9f4bb1a0   David Howells   KEYS: Use individ...
389
  		if (copy_to_user(buffer, buf->virt, datalen) != 0)
13100a72f   Kirill Marinushkin   Security: Keys: B...
390
391
392
393
394
  			ret = -EFAULT;
  
  err_fput:
  		fput(file);
  error:
d9f4bb1a0   David Howells   KEYS: Use individ...
395
  		big_key_free_buffer(buf);
ab3c3587f   David Howells   KEYS: Implement a...
396
397
  	} else {
  		ret = datalen;
146aa8b14   David Howells   KEYS: Merge the t...
398
399
  		if (copy_to_user(buffer, key->payload.data[big_key_data],
  				 datalen) != 0)
ab3c3587f   David Howells   KEYS: Implement a...
400
401
402
403
404
  			ret = -EFAULT;
  	}
  
  	return ret;
  }
13100a72f   Kirill Marinushkin   Security: Keys: B...
405
406
407
  /*
   * Register key type
   */
ab3c3587f   David Howells   KEYS: Implement a...
408
409
  static int __init big_key_init(void)
  {
7df3e59c3   David Howells   KEYS: Sort out bi...
410
  	int ret;
13100a72f   Kirill Marinushkin   Security: Keys: B...
411

13100a72f   Kirill Marinushkin   Security: Keys: B...
412
  	/* init block cipher */
428490e38   Jason A. Donenfeld   security/keys: re...
413
414
415
  	big_key_aead = crypto_alloc_aead(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
  	if (IS_ERR(big_key_aead)) {
  		ret = PTR_ERR(big_key_aead);
7df3e59c3   David Howells   KEYS: Sort out bi...
416
417
  		pr_err("Can't alloc crypto: %d
  ", ret);
428490e38   Jason A. Donenfeld   security/keys: re...
418
419
  		return ret;
  	}
a964f3956   Tycho Andersen   big key: get rid ...
420
421
422
423
424
425
  
  	if (unlikely(crypto_aead_ivsize(big_key_aead) != BIG_KEY_IV_SIZE)) {
  		WARN(1, "big key algorithm changed?");
  		ret = -EINVAL;
  		goto free_aead;
  	}
428490e38   Jason A. Donenfeld   security/keys: re...
426
427
428
429
430
  	ret = crypto_aead_setauthsize(big_key_aead, ENC_AUTHTAG_SIZE);
  	if (ret < 0) {
  		pr_err("Can't set crypto auth tag len: %d
  ", ret);
  		goto free_aead;
7df3e59c3   David Howells   KEYS: Sort out bi...
431
  	}
7df3e59c3   David Howells   KEYS: Sort out bi...
432
433
434
435
436
  
  	ret = register_key_type(&key_type_big_key);
  	if (ret < 0) {
  		pr_err("Can't register type: %d
  ", ret);
428490e38   Jason A. Donenfeld   security/keys: re...
437
  		goto free_aead;
13100a72f   Kirill Marinushkin   Security: Keys: B...
438
439
440
  	}
  
  	return 0;
428490e38   Jason A. Donenfeld   security/keys: re...
441
442
  free_aead:
  	crypto_free_aead(big_key_aead);
13100a72f   Kirill Marinushkin   Security: Keys: B...
443
444
  	return ret;
  }
7df3e59c3   David Howells   KEYS: Sort out bi...
445
  late_initcall(big_key_init);