aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/big_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/big_key.c')
-rw-r--r--security/keys/big_key.c139
1 files changed, 65 insertions, 74 deletions
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 6acb00f6f22c..e607830b6154 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -1,5 +1,6 @@
1/* Large capacity key type 1/* Large capacity key type
2 * 2 *
3 * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
3 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. 4 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 5 * Written by David Howells (dhowells@redhat.com)
5 * 6 *
@@ -16,10 +17,10 @@
16#include <linux/shmem_fs.h> 17#include <linux/shmem_fs.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include <linux/scatterlist.h> 19#include <linux/scatterlist.h>
20#include <linux/random.h>
19#include <keys/user-type.h> 21#include <keys/user-type.h>
20#include <keys/big_key-type.h> 22#include <keys/big_key-type.h>
21#include <crypto/rng.h> 23#include <crypto/aead.h>
22#include <crypto/skcipher.h>
23 24
24/* 25/*
25 * Layout of key payload words. 26 * Layout of key payload words.
@@ -49,7 +50,12 @@ enum big_key_op {
49/* 50/*
50 * Key size for big_key data encryption 51 * Key size for big_key data encryption
51 */ 52 */
52#define ENC_KEY_SIZE 16 53#define ENC_KEY_SIZE 32
54
55/*
56 * Authentication tag length
57 */
58#define ENC_AUTHTAG_SIZE 16
53 59
54/* 60/*
55 * big_key defined keys take an arbitrary string as the description and an 61 * big_key defined keys take an arbitrary string as the description and an
@@ -64,57 +70,62 @@ struct key_type key_type_big_key = {
64 .destroy = big_key_destroy, 70 .destroy = big_key_destroy,
65 .describe = big_key_describe, 71 .describe = big_key_describe,
66 .read = big_key_read, 72 .read = big_key_read,
73 /* no ->update(); don't add it without changing big_key_crypt() nonce */
67}; 74};
68 75
69/* 76/*
70 * Crypto names for big_key data encryption 77 * Crypto names for big_key data authenticated encryption
71 */ 78 */
72static const char big_key_rng_name[] = "stdrng"; 79static const char big_key_alg_name[] = "gcm(aes)";
73static const char big_key_alg_name[] = "ecb(aes)";
74 80
75/* 81/*
76 * Crypto algorithms for big_key data encryption 82 * Crypto algorithms for big_key data authenticated encryption
77 */ 83 */
78static struct crypto_rng *big_key_rng; 84static struct crypto_aead *big_key_aead;
79static struct crypto_skcipher *big_key_skcipher;
80 85
81/* 86/*
82 * Generate random key to encrypt big_key data 87 * Since changing the key affects the entire object, we need a mutex.
83 */ 88 */
84static inline int big_key_gen_enckey(u8 *key) 89static DEFINE_MUTEX(big_key_aead_lock);
85{
86 return crypto_rng_get_bytes(big_key_rng, key, ENC_KEY_SIZE);
87}
88 90
89/* 91/*
90 * Encrypt/decrypt big_key data 92 * Encrypt/decrypt big_key data
91 */ 93 */
92static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) 94static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
93{ 95{
94 int ret = -EINVAL; 96 int ret;
95 struct scatterlist sgio; 97 struct scatterlist sgio;
96 SKCIPHER_REQUEST_ON_STACK(req, big_key_skcipher); 98 struct aead_request *aead_req;
97 99 /* We always use a zero nonce. The reason we can get away with this is
98 if (crypto_skcipher_setkey(big_key_skcipher, key, ENC_KEY_SIZE)) { 100 * because we're using a different randomly generated key for every
101 * different encryption. Notably, too, key_type_big_key doesn't define
102 * an .update function, so there's no chance we'll wind up reusing the
103 * key to encrypt updated data. Simply put: one key, one encryption.
104 */
105 u8 zero_nonce[crypto_aead_ivsize(big_key_aead)];
106
107 aead_req = aead_request_alloc(big_key_aead, GFP_KERNEL);
108 if (!aead_req)
109 return -ENOMEM;
110
111 memset(zero_nonce, 0, sizeof(zero_nonce));
112 sg_init_one(&sgio, data, datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0));
113 aead_request_set_crypt(aead_req, &sgio, &sgio, datalen, zero_nonce);
114 aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
115 aead_request_set_ad(aead_req, 0);
116
117 mutex_lock(&big_key_aead_lock);
118 if (crypto_aead_setkey(big_key_aead, key, ENC_KEY_SIZE)) {
99 ret = -EAGAIN; 119 ret = -EAGAIN;
100 goto error; 120 goto error;
101 } 121 }
102
103 skcipher_request_set_tfm(req, big_key_skcipher);
104 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
105 NULL, NULL);
106
107 sg_init_one(&sgio, data, datalen);
108 skcipher_request_set_crypt(req, &sgio, &sgio, datalen, NULL);
109
110 if (op == BIG_KEY_ENC) 122 if (op == BIG_KEY_ENC)
111 ret = crypto_skcipher_encrypt(req); 123 ret = crypto_aead_encrypt(aead_req);
112 else 124 else
113 ret = crypto_skcipher_decrypt(req); 125 ret = crypto_aead_decrypt(aead_req);
114
115 skcipher_request_zero(req);
116
117error: 126error:
127 mutex_unlock(&big_key_aead_lock);
128 aead_request_free(aead_req);
118 return ret; 129 return ret;
119} 130}
120 131
@@ -146,16 +157,13 @@ int big_key_preparse(struct key_preparsed_payload *prep)
146 * 157 *
147 * File content is stored encrypted with randomly generated key. 158 * File content is stored encrypted with randomly generated key.
148 */ 159 */
149 size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher)); 160 size_t enclen = datalen + ENC_AUTHTAG_SIZE;
150 loff_t pos = 0; 161 loff_t pos = 0;
151 162
152 /* prepare aligned data to encrypt */
153 data = kmalloc(enclen, GFP_KERNEL); 163 data = kmalloc(enclen, GFP_KERNEL);
154 if (!data) 164 if (!data)
155 return -ENOMEM; 165 return -ENOMEM;
156
157 memcpy(data, prep->data, datalen); 166 memcpy(data, prep->data, datalen);
158 memset(data + datalen, 0x00, enclen - datalen);
159 167
160 /* generate random key */ 168 /* generate random key */
161 enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL); 169 enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
@@ -163,13 +171,12 @@ int big_key_preparse(struct key_preparsed_payload *prep)
163 ret = -ENOMEM; 171 ret = -ENOMEM;
164 goto error; 172 goto error;
165 } 173 }
166 174 ret = get_random_bytes_wait(enckey, ENC_KEY_SIZE);
167 ret = big_key_gen_enckey(enckey); 175 if (unlikely(ret))
168 if (ret)
169 goto err_enckey; 176 goto err_enckey;
170 177
171 /* encrypt aligned data */ 178 /* encrypt aligned data */
172 ret = big_key_crypt(BIG_KEY_ENC, data, enclen, enckey); 179 ret = big_key_crypt(BIG_KEY_ENC, data, datalen, enckey);
173 if (ret) 180 if (ret)
174 goto err_enckey; 181 goto err_enckey;
175 182
@@ -195,7 +202,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
195 *path = file->f_path; 202 *path = file->f_path;
196 path_get(path); 203 path_get(path);
197 fput(file); 204 fput(file);
198 kfree(data); 205 kzfree(data);
199 } else { 206 } else {
200 /* Just store the data in a buffer */ 207 /* Just store the data in a buffer */
201 void *data = kmalloc(datalen, GFP_KERNEL); 208 void *data = kmalloc(datalen, GFP_KERNEL);
@@ -211,9 +218,9 @@ int big_key_preparse(struct key_preparsed_payload *prep)
211err_fput: 218err_fput:
212 fput(file); 219 fput(file);
213err_enckey: 220err_enckey:
214 kfree(enckey); 221 kzfree(enckey);
215error: 222error:
216 kfree(data); 223 kzfree(data);
217 return ret; 224 return ret;
218} 225}
219 226
@@ -227,7 +234,7 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
227 234
228 path_put(path); 235 path_put(path);
229 } 236 }
230 kfree(prep->payload.data[big_key_data]); 237 kzfree(prep->payload.data[big_key_data]);
231} 238}
232 239
233/* 240/*
@@ -259,7 +266,7 @@ void big_key_destroy(struct key *key)
259 path->mnt = NULL; 266 path->mnt = NULL;
260 path->dentry = NULL; 267 path->dentry = NULL;
261 } 268 }
262 kfree(key->payload.data[big_key_data]); 269 kzfree(key->payload.data[big_key_data]);
263 key->payload.data[big_key_data] = NULL; 270 key->payload.data[big_key_data] = NULL;
264} 271}
265 272
@@ -295,7 +302,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
295 struct file *file; 302 struct file *file;
296 u8 *data; 303 u8 *data;
297 u8 *enckey = (u8 *)key->payload.data[big_key_data]; 304 u8 *enckey = (u8 *)key->payload.data[big_key_data];
298 size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher)); 305 size_t enclen = datalen + ENC_AUTHTAG_SIZE;
299 loff_t pos = 0; 306 loff_t pos = 0;
300 307
301 data = kmalloc(enclen, GFP_KERNEL); 308 data = kmalloc(enclen, GFP_KERNEL);
@@ -328,7 +335,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
328err_fput: 335err_fput:
329 fput(file); 336 fput(file);
330error: 337error:
331 kfree(data); 338 kzfree(data);
332 } else { 339 } else {
333 ret = datalen; 340 ret = datalen;
334 if (copy_to_user(buffer, key->payload.data[big_key_data], 341 if (copy_to_user(buffer, key->payload.data[big_key_data],
@@ -344,47 +351,31 @@ error:
344 */ 351 */
345static int __init big_key_init(void) 352static int __init big_key_init(void)
346{ 353{
347 struct crypto_skcipher *cipher;
348 struct crypto_rng *rng;
349 int ret; 354 int ret;
350 355
351 rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
352 if (IS_ERR(rng)) {
353 pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
354 return PTR_ERR(rng);
355 }
356
357 big_key_rng = rng;
358
359 /* seed RNG */
360 ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
361 if (ret) {
362 pr_err("Can't reset rng: %d\n", ret);
363 goto error_rng;
364 }
365
366 /* init block cipher */ 356 /* init block cipher */
367 cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC); 357 big_key_aead = crypto_alloc_aead(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
368 if (IS_ERR(cipher)) { 358 if (IS_ERR(big_key_aead)) {
369 ret = PTR_ERR(cipher); 359 ret = PTR_ERR(big_key_aead);
370 pr_err("Can't alloc crypto: %d\n", ret); 360 pr_err("Can't alloc crypto: %d\n", ret);
371 goto error_rng; 361 return ret;
362 }
363 ret = crypto_aead_setauthsize(big_key_aead, ENC_AUTHTAG_SIZE);
364 if (ret < 0) {
365 pr_err("Can't set crypto auth tag len: %d\n", ret);
366 goto free_aead;
372 } 367 }
373
374 big_key_skcipher = cipher;
375 368
376 ret = register_key_type(&key_type_big_key); 369 ret = register_key_type(&key_type_big_key);
377 if (ret < 0) { 370 if (ret < 0) {
378 pr_err("Can't register type: %d\n", ret); 371 pr_err("Can't register type: %d\n", ret);
379 goto error_cipher; 372 goto free_aead;
380 } 373 }
381 374
382 return 0; 375 return 0;
383 376
384error_cipher: 377free_aead:
385 crypto_free_skcipher(big_key_skcipher); 378 crypto_free_aead(big_key_aead);
386error_rng:
387 crypto_free_rng(big_key_rng);
388 return ret; 379 return ret;
389} 380}
390 381