blob: f36a105de791e393ff7dc3f049da58377f44e4df [file] [log] [blame]
Mimi Zohar7e70cb42010-11-23 18:55:35 -05001/*
2 * Copyright (C) 2010 IBM Corporation
3 *
4 * Author:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2 of the License.
10 *
Randy Dunlapd410fa42011-05-19 15:59:38 -070011 * See Documentation/security/keys-trusted-encrypted.txt
Mimi Zohar7e70cb42010-11-23 18:55:35 -050012 */
13
14#include <linux/uaccess.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/parser.h>
19#include <linux/string.h>
Mimi Zohar93ae86e2010-11-29 16:20:04 -050020#include <linux/err.h>
Mimi Zohar7e70cb42010-11-23 18:55:35 -050021#include <keys/user-type.h>
22#include <keys/trusted-type.h>
23#include <keys/encrypted-type.h>
24#include <linux/key-type.h>
25#include <linux/random.h>
26#include <linux/rcupdate.h>
27#include <linux/scatterlist.h>
28#include <linux/crypto.h>
29#include <crypto/hash.h>
30#include <crypto/sha.h>
31#include <crypto/aes.h>
32
Mimi Zoharb9703442011-01-18 09:07:12 -050033#include "encrypted.h"
Mimi Zohar7e70cb42010-11-23 18:55:35 -050034
Mimi Zohar3b1826c2010-12-13 16:53:13 -050035static const char KEY_TRUSTED_PREFIX[] = "trusted:";
36static const char KEY_USER_PREFIX[] = "user:";
Mimi Zohar7e70cb42010-11-23 18:55:35 -050037static const char hash_alg[] = "sha256";
38static const char hmac_alg[] = "hmac(sha256)";
39static const char blkcipher_alg[] = "cbc(aes)";
40static unsigned int ivsize;
41static int blksize;
42
Mimi Zohar3b1826c2010-12-13 16:53:13 -050043#define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
44#define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
45#define HASH_SIZE SHA256_DIGEST_SIZE
46#define MAX_DATA_SIZE 4096
47#define MIN_DATA_SIZE 20
48
Mimi Zohar7e70cb42010-11-23 18:55:35 -050049struct sdesc {
50 struct shash_desc shash;
51 char ctx[];
52};
53
54static struct crypto_shash *hashalg;
55static struct crypto_shash *hmacalg;
56
57enum {
58 Opt_err = -1, Opt_new, Opt_load, Opt_update
59};
60
61static const match_table_t key_tokens = {
62 {Opt_new, "new"},
63 {Opt_load, "load"},
64 {Opt_update, "update"},
65 {Opt_err, NULL}
66};
67
68static int aes_get_sizes(void)
69{
70 struct crypto_blkcipher *tfm;
71
72 tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
73 if (IS_ERR(tfm)) {
74 pr_err("encrypted_key: failed to alloc_cipher (%ld)\n",
75 PTR_ERR(tfm));
76 return PTR_ERR(tfm);
77 }
78 ivsize = crypto_blkcipher_ivsize(tfm);
79 blksize = crypto_blkcipher_blocksize(tfm);
80 crypto_free_blkcipher(tfm);
81 return 0;
82}
83
84/*
85 * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key
86 *
Roberto Sassu08fa2aa2011-06-27 13:45:40 +020087 * key-type:= "trusted:" | "user:"
Mimi Zohar7e70cb42010-11-23 18:55:35 -050088 * desc:= master-key description
89 *
90 * Verify that 'key-type' is valid and that 'desc' exists. On key update,
91 * only the master key description is permitted to change, not the key-type.
92 * The key-type remains constant.
93 *
94 * On success returns 0, otherwise -EINVAL.
95 */
96static int valid_master_desc(const char *new_desc, const char *orig_desc)
97{
98 if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) {
99 if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN)
100 goto out;
101 if (orig_desc)
102 if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN))
103 goto out;
104 } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) {
105 if (strlen(new_desc) == KEY_USER_PREFIX_LEN)
106 goto out;
107 if (orig_desc)
108 if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN))
109 goto out;
110 } else
111 goto out;
112 return 0;
113out:
114 return -EINVAL;
115}
116
117/*
118 * datablob_parse - parse the keyctl data
119 *
120 * datablob format:
121 * new <master-key name> <decrypted data length>
122 * load <master-key name> <decrypted data length> <encrypted iv + data>
123 * update <new-master-key name>
124 *
125 * Tokenizes a copy of the keyctl data, returning a pointer to each token,
126 * which is null terminated.
127 *
128 * On success returns 0, otherwise -EINVAL.
129 */
130static int datablob_parse(char *datablob, char **master_desc,
Mimi Zohar1f350652010-12-13 16:53:12 -0500131 char **decrypted_datalen, char **hex_encoded_iv)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500132{
133 substring_t args[MAX_OPT_ARGS];
134 int ret = -EINVAL;
135 int key_cmd;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200136 char *keyword;
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500137
Roberto Sassu7103dff2011-06-27 13:45:41 +0200138 keyword = strsep(&datablob, " \t");
139 if (!keyword) {
140 pr_info("encrypted_key: insufficient parameters specified\n");
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500141 return ret;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200142 }
143 key_cmd = match_token(keyword, key_tokens, args);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500144
145 *master_desc = strsep(&datablob, " \t");
Roberto Sassu7103dff2011-06-27 13:45:41 +0200146 if (!*master_desc) {
147 pr_info("encrypted_key: master key parameter is missing\n");
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500148 goto out;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200149 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500150
Roberto Sassu7103dff2011-06-27 13:45:41 +0200151 if (valid_master_desc(*master_desc, NULL) < 0) {
152 pr_info("encrypted_key: master key parameter \'%s\' "
153 "is invalid\n", *master_desc);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500154 goto out;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200155 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500156
157 if (decrypted_datalen) {
158 *decrypted_datalen = strsep(&datablob, " \t");
Roberto Sassu7103dff2011-06-27 13:45:41 +0200159 if (!*decrypted_datalen) {
160 pr_info("encrypted_key: keylen parameter is missing\n");
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500161 goto out;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200162 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500163 }
164
165 switch (key_cmd) {
166 case Opt_new:
Roberto Sassu7103dff2011-06-27 13:45:41 +0200167 if (!decrypted_datalen) {
168 pr_info("encrypted_key: keyword \'%s\' not allowed "
169 "when called from .update method\n", keyword);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500170 break;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200171 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500172 ret = 0;
173 break;
174 case Opt_load:
Roberto Sassu7103dff2011-06-27 13:45:41 +0200175 if (!decrypted_datalen) {
176 pr_info("encrypted_key: keyword \'%s\' not allowed "
177 "when called from .update method\n", keyword);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500178 break;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200179 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500180 *hex_encoded_iv = strsep(&datablob, " \t");
Roberto Sassu7103dff2011-06-27 13:45:41 +0200181 if (!*hex_encoded_iv) {
182 pr_info("encrypted_key: hex blob is missing\n");
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500183 break;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200184 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500185 ret = 0;
186 break;
187 case Opt_update:
Roberto Sassu7103dff2011-06-27 13:45:41 +0200188 if (decrypted_datalen) {
189 pr_info("encrypted_key: keyword \'%s\' not allowed "
190 "when called from .instantiate method\n",
191 keyword);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500192 break;
Roberto Sassu7103dff2011-06-27 13:45:41 +0200193 }
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500194 ret = 0;
195 break;
196 case Opt_err:
Roberto Sassu7103dff2011-06-27 13:45:41 +0200197 pr_info("encrypted_key: keyword \'%s\' not recognized\n",
198 keyword);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500199 break;
200 }
201out:
202 return ret;
203}
204
205/*
206 * datablob_format - format as an ascii string, before copying to userspace
207 */
208static char *datablob_format(struct encrypted_key_payload *epayload,
209 size_t asciiblob_len)
210{
211 char *ascii_buf, *bufp;
212 u8 *iv = epayload->iv;
213 int len;
214 int i;
215
216 ascii_buf = kmalloc(asciiblob_len + 1, GFP_KERNEL);
217 if (!ascii_buf)
218 goto out;
219
220 ascii_buf[asciiblob_len] = '\0';
221
222 /* copy datablob master_desc and datalen strings */
223 len = sprintf(ascii_buf, "%s %s ", epayload->master_desc,
224 epayload->datalen);
225
226 /* convert the hex encoded iv, encrypted-data and HMAC to ascii */
227 bufp = &ascii_buf[len];
228 for (i = 0; i < (asciiblob_len - len) / 2; i++)
229 bufp = pack_hex_byte(bufp, iv[i]);
230out:
231 return ascii_buf;
232}
233
234/*
235 * request_trusted_key - request the trusted key
236 *
237 * Trusted keys are sealed to PCRs and other metadata. Although userspace
238 * manages both trusted/encrypted key-types, like the encrypted key type
239 * data, trusted key type data is not visible decrypted from userspace.
240 */
241static struct key *request_trusted_key(const char *trusted_desc,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500242 u8 **master_key, size_t *master_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500243{
244 struct trusted_key_payload *tpayload;
245 struct key *tkey;
246
247 tkey = request_key(&key_type_trusted, trusted_desc, NULL);
248 if (IS_ERR(tkey))
249 goto error;
250
251 down_read(&tkey->sem);
252 tpayload = rcu_dereference(tkey->payload.data);
253 *master_key = tpayload->key;
254 *master_keylen = tpayload->key_len;
255error:
256 return tkey;
257}
258
259/*
260 * request_user_key - request the user key
261 *
262 * Use a user provided key to encrypt/decrypt an encrypted-key.
263 */
264static struct key *request_user_key(const char *master_desc, u8 **master_key,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500265 size_t *master_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500266{
267 struct user_key_payload *upayload;
268 struct key *ukey;
269
270 ukey = request_key(&key_type_user, master_desc, NULL);
271 if (IS_ERR(ukey))
272 goto error;
273
274 down_read(&ukey->sem);
275 upayload = rcu_dereference(ukey->payload.data);
276 *master_key = upayload->data;
277 *master_keylen = upayload->datalen;
278error:
279 return ukey;
280}
281
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500282static struct sdesc *alloc_sdesc(struct crypto_shash *alg)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500283{
284 struct sdesc *sdesc;
285 int size;
286
287 size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
288 sdesc = kmalloc(size, GFP_KERNEL);
289 if (!sdesc)
290 return ERR_PTR(-ENOMEM);
291 sdesc->shash.tfm = alg;
292 sdesc->shash.flags = 0x0;
293 return sdesc;
294}
295
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500296static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
297 const u8 *buf, unsigned int buflen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500298{
299 struct sdesc *sdesc;
300 int ret;
301
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500302 sdesc = alloc_sdesc(hmacalg);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500303 if (IS_ERR(sdesc)) {
304 pr_info("encrypted_key: can't alloc %s\n", hmac_alg);
305 return PTR_ERR(sdesc);
306 }
307
308 ret = crypto_shash_setkey(hmacalg, key, keylen);
309 if (!ret)
310 ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest);
311 kfree(sdesc);
312 return ret;
313}
314
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500315static int calc_hash(u8 *digest, const u8 *buf, unsigned int buflen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500316{
317 struct sdesc *sdesc;
318 int ret;
319
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500320 sdesc = alloc_sdesc(hashalg);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500321 if (IS_ERR(sdesc)) {
322 pr_info("encrypted_key: can't alloc %s\n", hash_alg);
323 return PTR_ERR(sdesc);
324 }
325
326 ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest);
327 kfree(sdesc);
328 return ret;
329}
330
331enum derived_key_type { ENC_KEY, AUTH_KEY };
332
333/* Derive authentication/encryption key from trusted key */
334static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500335 const u8 *master_key, size_t master_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500336{
337 u8 *derived_buf;
338 unsigned int derived_buf_len;
339 int ret;
340
341 derived_buf_len = strlen("AUTH_KEY") + 1 + master_keylen;
342 if (derived_buf_len < HASH_SIZE)
343 derived_buf_len = HASH_SIZE;
344
345 derived_buf = kzalloc(derived_buf_len, GFP_KERNEL);
346 if (!derived_buf) {
347 pr_err("encrypted_key: out of memory\n");
348 return -ENOMEM;
349 }
350 if (key_type)
351 strcpy(derived_buf, "AUTH_KEY");
352 else
353 strcpy(derived_buf, "ENC_KEY");
354
355 memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
356 master_keylen);
357 ret = calc_hash(derived_key, derived_buf, derived_buf_len);
358 kfree(derived_buf);
359 return ret;
360}
361
362static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500363 unsigned int key_len, const u8 *iv,
364 unsigned int ivsize)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500365{
366 int ret;
367
368 desc->tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
369 if (IS_ERR(desc->tfm)) {
370 pr_err("encrypted_key: failed to load %s transform (%ld)\n",
371 blkcipher_alg, PTR_ERR(desc->tfm));
372 return PTR_ERR(desc->tfm);
373 }
374 desc->flags = 0;
375
376 ret = crypto_blkcipher_setkey(desc->tfm, key, key_len);
377 if (ret < 0) {
378 pr_err("encrypted_key: failed to setkey (%d)\n", ret);
379 crypto_free_blkcipher(desc->tfm);
380 return ret;
381 }
382 crypto_blkcipher_set_iv(desc->tfm, iv, ivsize);
383 return 0;
384}
385
386static struct key *request_master_key(struct encrypted_key_payload *epayload,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500387 u8 **master_key, size_t *master_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500388{
389 struct key *mkey = NULL;
390
391 if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX,
392 KEY_TRUSTED_PREFIX_LEN)) {
393 mkey = request_trusted_key(epayload->master_desc +
394 KEY_TRUSTED_PREFIX_LEN,
395 master_key, master_keylen);
396 } else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX,
397 KEY_USER_PREFIX_LEN)) {
398 mkey = request_user_key(epayload->master_desc +
399 KEY_USER_PREFIX_LEN,
400 master_key, master_keylen);
401 } else
402 goto out;
403
Roberto Sassuf91c2c52011-06-27 13:45:39 +0200404 if (IS_ERR(mkey)) {
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500405 pr_info("encrypted_key: key %s not found",
406 epayload->master_desc);
Roberto Sassuf91c2c52011-06-27 13:45:39 +0200407 goto out;
408 }
409
410 dump_master_key(*master_key, *master_keylen);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500411out:
412 return mkey;
413}
414
415/* Before returning data to userspace, encrypt decrypted data. */
416static int derived_key_encrypt(struct encrypted_key_payload *epayload,
417 const u8 *derived_key,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500418 unsigned int derived_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500419{
420 struct scatterlist sg_in[2];
421 struct scatterlist sg_out[1];
422 struct blkcipher_desc desc;
423 unsigned int encrypted_datalen;
424 unsigned int padlen;
425 char pad[16];
426 int ret;
427
428 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
429 padlen = encrypted_datalen - epayload->decrypted_datalen;
430
431 ret = init_blkcipher_desc(&desc, derived_key, derived_keylen,
432 epayload->iv, ivsize);
433 if (ret < 0)
434 goto out;
435 dump_decrypted_data(epayload);
436
437 memset(pad, 0, sizeof pad);
438 sg_init_table(sg_in, 2);
439 sg_set_buf(&sg_in[0], epayload->decrypted_data,
440 epayload->decrypted_datalen);
441 sg_set_buf(&sg_in[1], pad, padlen);
442
443 sg_init_table(sg_out, 1);
444 sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
445
446 ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, encrypted_datalen);
447 crypto_free_blkcipher(desc.tfm);
448 if (ret < 0)
449 pr_err("encrypted_key: failed to encrypt (%d)\n", ret);
450 else
451 dump_encrypted_data(epayload, encrypted_datalen);
452out:
453 return ret;
454}
455
456static int datablob_hmac_append(struct encrypted_key_payload *epayload,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500457 const u8 *master_key, size_t master_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500458{
459 u8 derived_key[HASH_SIZE];
460 u8 *digest;
461 int ret;
462
463 ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
464 if (ret < 0)
465 goto out;
466
467 digest = epayload->master_desc + epayload->datablob_len;
468 ret = calc_hmac(digest, derived_key, sizeof derived_key,
469 epayload->master_desc, epayload->datablob_len);
470 if (!ret)
471 dump_hmac(NULL, digest, HASH_SIZE);
472out:
473 return ret;
474}
475
476/* verify HMAC before decrypting encrypted key */
477static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500478 const u8 *master_key, size_t master_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500479{
480 u8 derived_key[HASH_SIZE];
481 u8 digest[HASH_SIZE];
482 int ret;
483
484 ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
485 if (ret < 0)
486 goto out;
487
488 ret = calc_hmac(digest, derived_key, sizeof derived_key,
489 epayload->master_desc, epayload->datablob_len);
490 if (ret < 0)
491 goto out;
492 ret = memcmp(digest, epayload->master_desc + epayload->datablob_len,
493 sizeof digest);
494 if (ret) {
495 ret = -EINVAL;
496 dump_hmac("datablob",
497 epayload->master_desc + epayload->datablob_len,
498 HASH_SIZE);
499 dump_hmac("calc", digest, HASH_SIZE);
500 }
501out:
502 return ret;
503}
504
505static int derived_key_decrypt(struct encrypted_key_payload *epayload,
506 const u8 *derived_key,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500507 unsigned int derived_keylen)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500508{
509 struct scatterlist sg_in[1];
510 struct scatterlist sg_out[2];
511 struct blkcipher_desc desc;
512 unsigned int encrypted_datalen;
513 char pad[16];
514 int ret;
515
516 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
517 ret = init_blkcipher_desc(&desc, derived_key, derived_keylen,
518 epayload->iv, ivsize);
519 if (ret < 0)
520 goto out;
521 dump_encrypted_data(epayload, encrypted_datalen);
522
523 memset(pad, 0, sizeof pad);
524 sg_init_table(sg_in, 1);
525 sg_init_table(sg_out, 2);
526 sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen);
527 sg_set_buf(&sg_out[0], epayload->decrypted_data,
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500528 epayload->decrypted_datalen);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500529 sg_set_buf(&sg_out[1], pad, sizeof pad);
530
531 ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, encrypted_datalen);
532 crypto_free_blkcipher(desc.tfm);
533 if (ret < 0)
534 goto out;
535 dump_decrypted_data(epayload);
536out:
537 return ret;
538}
539
540/* Allocate memory for decrypted key and datablob. */
541static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
542 const char *master_desc,
543 const char *datalen)
544{
545 struct encrypted_key_payload *epayload = NULL;
546 unsigned short datablob_len;
547 unsigned short decrypted_datalen;
548 unsigned int encrypted_datalen;
549 long dlen;
550 int ret;
551
552 ret = strict_strtol(datalen, 10, &dlen);
553 if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE)
554 return ERR_PTR(-EINVAL);
555
556 decrypted_datalen = dlen;
557 encrypted_datalen = roundup(decrypted_datalen, blksize);
558
559 datablob_len = strlen(master_desc) + 1 + strlen(datalen) + 1
560 + ivsize + 1 + encrypted_datalen;
561
562 ret = key_payload_reserve(key, decrypted_datalen + datablob_len
563 + HASH_SIZE + 1);
564 if (ret < 0)
565 return ERR_PTR(ret);
566
567 epayload = kzalloc(sizeof(*epayload) + decrypted_datalen +
568 datablob_len + HASH_SIZE + 1, GFP_KERNEL);
569 if (!epayload)
570 return ERR_PTR(-ENOMEM);
571
572 epayload->decrypted_datalen = decrypted_datalen;
573 epayload->datablob_len = datablob_len;
574 return epayload;
575}
576
577static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
Mimi Zohar1f350652010-12-13 16:53:12 -0500578 const char *hex_encoded_iv)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500579{
580 struct key *mkey;
581 u8 derived_key[HASH_SIZE];
582 u8 *master_key;
583 u8 *hmac;
Mimi Zohar1f350652010-12-13 16:53:12 -0500584 const char *hex_encoded_data;
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500585 unsigned int encrypted_datalen;
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500586 size_t master_keylen;
Mimi Zohar1f350652010-12-13 16:53:12 -0500587 size_t asciilen;
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500588 int ret;
589
590 encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
Mimi Zohar1f350652010-12-13 16:53:12 -0500591 asciilen = (ivsize + 1 + encrypted_datalen + HASH_SIZE) * 2;
592 if (strlen(hex_encoded_iv) != asciilen)
593 return -EINVAL;
594
595 hex_encoded_data = hex_encoded_iv + (2 * ivsize) + 2;
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500596 hex2bin(epayload->iv, hex_encoded_iv, ivsize);
597 hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen);
598
599 hmac = epayload->master_desc + epayload->datablob_len;
600 hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE);
601
602 mkey = request_master_key(epayload, &master_key, &master_keylen);
603 if (IS_ERR(mkey))
604 return PTR_ERR(mkey);
605
606 ret = datablob_hmac_verify(epayload, master_key, master_keylen);
607 if (ret < 0) {
608 pr_err("encrypted_key: bad hmac (%d)\n", ret);
609 goto out;
610 }
611
612 ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
613 if (ret < 0)
614 goto out;
615
616 ret = derived_key_decrypt(epayload, derived_key, sizeof derived_key);
617 if (ret < 0)
618 pr_err("encrypted_key: failed to decrypt key (%d)\n", ret);
619out:
620 up_read(&mkey->sem);
621 key_put(mkey);
622 return ret;
623}
624
625static void __ekey_init(struct encrypted_key_payload *epayload,
626 const char *master_desc, const char *datalen)
627{
628 epayload->master_desc = epayload->decrypted_data
629 + epayload->decrypted_datalen;
630 epayload->datalen = epayload->master_desc + strlen(master_desc) + 1;
631 epayload->iv = epayload->datalen + strlen(datalen) + 1;
632 epayload->encrypted_data = epayload->iv + ivsize + 1;
633
634 memcpy(epayload->master_desc, master_desc, strlen(master_desc));
635 memcpy(epayload->datalen, datalen, strlen(datalen));
636}
637
638/*
639 * encrypted_init - initialize an encrypted key
640 *
641 * For a new key, use a random number for both the iv and data
642 * itself. For an old key, decrypt the hex encoded data.
643 */
644static int encrypted_init(struct encrypted_key_payload *epayload,
645 const char *master_desc, const char *datalen,
Mimi Zohar1f350652010-12-13 16:53:12 -0500646 const char *hex_encoded_iv)
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500647{
648 int ret = 0;
649
650 __ekey_init(epayload, master_desc, datalen);
Mimi Zohar1f350652010-12-13 16:53:12 -0500651 if (!hex_encoded_iv) {
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500652 get_random_bytes(epayload->iv, ivsize);
653
654 get_random_bytes(epayload->decrypted_data,
655 epayload->decrypted_datalen);
656 } else
Mimi Zohar1f350652010-12-13 16:53:12 -0500657 ret = encrypted_key_decrypt(epayload, hex_encoded_iv);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500658 return ret;
659}
660
661/*
662 * encrypted_instantiate - instantiate an encrypted key
663 *
664 * Decrypt an existing encrypted datablob or create a new encrypted key
665 * based on a kernel random number.
666 *
667 * On success, return 0. Otherwise return errno.
668 */
669static int encrypted_instantiate(struct key *key, const void *data,
670 size_t datalen)
671{
672 struct encrypted_key_payload *epayload = NULL;
673 char *datablob = NULL;
674 char *master_desc = NULL;
675 char *decrypted_datalen = NULL;
676 char *hex_encoded_iv = NULL;
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500677 int ret;
678
679 if (datalen <= 0 || datalen > 32767 || !data)
680 return -EINVAL;
681
682 datablob = kmalloc(datalen + 1, GFP_KERNEL);
683 if (!datablob)
684 return -ENOMEM;
685 datablob[datalen] = 0;
686 memcpy(datablob, data, datalen);
687 ret = datablob_parse(datablob, &master_desc, &decrypted_datalen,
Mimi Zohar1f350652010-12-13 16:53:12 -0500688 &hex_encoded_iv);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500689 if (ret < 0)
690 goto out;
691
692 epayload = encrypted_key_alloc(key, master_desc, decrypted_datalen);
693 if (IS_ERR(epayload)) {
694 ret = PTR_ERR(epayload);
695 goto out;
696 }
697 ret = encrypted_init(epayload, master_desc, decrypted_datalen,
Mimi Zohar1f350652010-12-13 16:53:12 -0500698 hex_encoded_iv);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500699 if (ret < 0) {
700 kfree(epayload);
701 goto out;
702 }
703
704 rcu_assign_pointer(key->payload.data, epayload);
705out:
706 kfree(datablob);
707 return ret;
708}
709
710static void encrypted_rcu_free(struct rcu_head *rcu)
711{
712 struct encrypted_key_payload *epayload;
713
714 epayload = container_of(rcu, struct encrypted_key_payload, rcu);
715 memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
716 kfree(epayload);
717}
718
719/*
720 * encrypted_update - update the master key description
721 *
722 * Change the master key description for an existing encrypted key.
723 * The next read will return an encrypted datablob using the new
724 * master key description.
725 *
726 * On success, return 0. Otherwise return errno.
727 */
728static int encrypted_update(struct key *key, const void *data, size_t datalen)
729{
730 struct encrypted_key_payload *epayload = key->payload.data;
731 struct encrypted_key_payload *new_epayload;
732 char *buf;
733 char *new_master_desc = NULL;
734 int ret = 0;
735
736 if (datalen <= 0 || datalen > 32767 || !data)
737 return -EINVAL;
738
739 buf = kmalloc(datalen + 1, GFP_KERNEL);
740 if (!buf)
741 return -ENOMEM;
742
743 buf[datalen] = 0;
744 memcpy(buf, data, datalen);
Mimi Zohar1f350652010-12-13 16:53:12 -0500745 ret = datablob_parse(buf, &new_master_desc, NULL, NULL);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500746 if (ret < 0)
747 goto out;
748
749 ret = valid_master_desc(new_master_desc, epayload->master_desc);
750 if (ret < 0)
751 goto out;
752
753 new_epayload = encrypted_key_alloc(key, new_master_desc,
754 epayload->datalen);
755 if (IS_ERR(new_epayload)) {
756 ret = PTR_ERR(new_epayload);
757 goto out;
758 }
759
760 __ekey_init(new_epayload, new_master_desc, epayload->datalen);
761
762 memcpy(new_epayload->iv, epayload->iv, ivsize);
763 memcpy(new_epayload->decrypted_data, epayload->decrypted_data,
764 epayload->decrypted_datalen);
765
766 rcu_assign_pointer(key->payload.data, new_epayload);
767 call_rcu(&epayload->rcu, encrypted_rcu_free);
768out:
769 kfree(buf);
770 return ret;
771}
772
773/*
774 * encrypted_read - format and copy the encrypted data to userspace
775 *
776 * The resulting datablob format is:
777 * <master-key name> <decrypted data length> <encrypted iv> <encrypted data>
778 *
779 * On success, return to userspace the encrypted key datablob size.
780 */
781static long encrypted_read(const struct key *key, char __user *buffer,
782 size_t buflen)
783{
784 struct encrypted_key_payload *epayload;
785 struct key *mkey;
786 u8 *master_key;
Mimi Zohar3b1826c2010-12-13 16:53:13 -0500787 size_t master_keylen;
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500788 char derived_key[HASH_SIZE];
789 char *ascii_buf;
790 size_t asciiblob_len;
791 int ret;
792
David Howells633e8042011-03-07 15:05:51 +0000793 epayload = rcu_dereference_key(key);
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500794
795 /* returns the hex encoded iv, encrypted-data, and hmac as ascii */
796 asciiblob_len = epayload->datablob_len + ivsize + 1
797 + roundup(epayload->decrypted_datalen, blksize)
798 + (HASH_SIZE * 2);
799
800 if (!buffer || buflen < asciiblob_len)
801 return asciiblob_len;
802
803 mkey = request_master_key(epayload, &master_key, &master_keylen);
804 if (IS_ERR(mkey))
805 return PTR_ERR(mkey);
806
807 ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
808 if (ret < 0)
809 goto out;
810
811 ret = derived_key_encrypt(epayload, derived_key, sizeof derived_key);
812 if (ret < 0)
813 goto out;
814
815 ret = datablob_hmac_append(epayload, master_key, master_keylen);
816 if (ret < 0)
817 goto out;
818
819 ascii_buf = datablob_format(epayload, asciiblob_len);
820 if (!ascii_buf) {
821 ret = -ENOMEM;
822 goto out;
823 }
824
825 up_read(&mkey->sem);
826 key_put(mkey);
827
828 if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0)
829 ret = -EFAULT;
830 kfree(ascii_buf);
831
832 return asciiblob_len;
833out:
834 up_read(&mkey->sem);
835 key_put(mkey);
836 return ret;
837}
838
839/*
840 * encrypted_destroy - before freeing the key, clear the decrypted data
841 *
842 * Before freeing the key, clear the memory containing the decrypted
843 * key data.
844 */
845static void encrypted_destroy(struct key *key)
846{
847 struct encrypted_key_payload *epayload = key->payload.data;
848
849 if (!epayload)
850 return;
851
852 memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
853 kfree(key->payload.data);
854}
855
856struct key_type key_type_encrypted = {
857 .name = "encrypted",
858 .instantiate = encrypted_instantiate,
859 .update = encrypted_update,
860 .match = user_match,
861 .destroy = encrypted_destroy,
862 .describe = user_describe,
863 .read = encrypted_read,
864};
865EXPORT_SYMBOL_GPL(key_type_encrypted);
866
867static void encrypted_shash_release(void)
868{
869 if (hashalg)
870 crypto_free_shash(hashalg);
871 if (hmacalg)
872 crypto_free_shash(hmacalg);
873}
874
875static int __init encrypted_shash_alloc(void)
876{
877 int ret;
878
879 hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
880 if (IS_ERR(hmacalg)) {
881 pr_info("encrypted_key: could not allocate crypto %s\n",
882 hmac_alg);
883 return PTR_ERR(hmacalg);
884 }
885
886 hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
887 if (IS_ERR(hashalg)) {
888 pr_info("encrypted_key: could not allocate crypto %s\n",
889 hash_alg);
890 ret = PTR_ERR(hashalg);
891 goto hashalg_fail;
892 }
893
894 return 0;
895
896hashalg_fail:
897 crypto_free_shash(hmacalg);
898 return ret;
899}
900
901static int __init init_encrypted(void)
902{
903 int ret;
904
905 ret = encrypted_shash_alloc();
906 if (ret < 0)
907 return ret;
908 ret = register_key_type(&key_type_encrypted);
909 if (ret < 0)
910 goto out;
911 return aes_get_sizes();
912out:
913 encrypted_shash_release();
914 return ret;
Mimi Zoharb9703442011-01-18 09:07:12 -0500915
Mimi Zohar7e70cb42010-11-23 18:55:35 -0500916}
917
918static void __exit cleanup_encrypted(void)
919{
920 encrypted_shash_release();
921 unregister_key_type(&key_type_encrypted);
922}
923
924late_initcall(init_encrypted);
925module_exit(cleanup_encrypted);
926
927MODULE_LICENSE("GPL");