aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2006-10-03 04:15:37 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:15 -0400
commite48d4bbf9697f4fee4f4e48c5e2586b332809519 (patch)
treeeef2172f5730c17ace6ddb9a1cf6a4f5062176ae
parent8757b7764f13e336f3c0eb1f634440d4ee4c3a67 (diff)
[PATCH] dm crypt: add key msg
Add the facility to wipe the encryption key from memory (for example while a laptop is suspended) and reinstate it later (when the laptop gets resumed). Signed-off-by: Milan Broz <mbroz@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/dm-crypt.c97
1 files changed, 91 insertions, 6 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index bdbd34993a80..e1e8040f451a 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright (C) 2003 Christophe Saout <christophe@saout.de> 2 * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
3 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> 3 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
4 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
4 * 5 *
5 * This file is released under the GPL. 6 * This file is released under the GPL.
6 */ 7 */
@@ -22,6 +23,7 @@
22#include "dm.h" 23#include "dm.h"
23 24
24#define DM_MSG_PREFIX "crypt" 25#define DM_MSG_PREFIX "crypt"
26#define MESG_STR(x) x, sizeof(x)
25 27
26/* 28/*
27 * per bio private data 29 * per bio private data
@@ -63,6 +65,7 @@ struct crypt_iv_operations {
63 * Crypt: maps a linear range of a block device 65 * Crypt: maps a linear range of a block device
64 * and encrypts / decrypts at the same time. 66 * and encrypts / decrypts at the same time.
65 */ 67 */
68enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
66struct crypt_config { 69struct crypt_config {
67 struct dm_dev *dev; 70 struct dm_dev *dev;
68 sector_t start; 71 sector_t start;
@@ -86,6 +89,7 @@ struct crypt_config {
86 char cipher[CRYPTO_MAX_ALG_NAME]; 89 char cipher[CRYPTO_MAX_ALG_NAME];
87 char chainmode[CRYPTO_MAX_ALG_NAME]; 90 char chainmode[CRYPTO_MAX_ALG_NAME];
88 struct crypto_blkcipher *tfm; 91 struct crypto_blkcipher *tfm;
92 unsigned long flags;
89 unsigned int key_size; 93 unsigned int key_size;
90 u8 key[0]; 94 u8 key[0];
91}; 95};
@@ -507,6 +511,31 @@ static void crypt_encode_key(char *hex, u8 *key, unsigned int size)
507 } 511 }
508} 512}
509 513
514static int crypt_set_key(struct crypt_config *cc, char *key)
515{
516 unsigned key_size = strlen(key) >> 1;
517
518 if (cc->key_size && cc->key_size != key_size)
519 return -EINVAL;
520
521 cc->key_size = key_size; /* initial settings */
522
523 if ((!key_size && strcmp(key, "-")) ||
524 (key_size && crypt_decode_key(cc->key, key, key_size) < 0))
525 return -EINVAL;
526
527 set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
528
529 return 0;
530}
531
532static int crypt_wipe_key(struct crypt_config *cc)
533{
534 clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
535 memset(&cc->key, 0, cc->key_size * sizeof(u8));
536 return 0;
537}
538
510/* 539/*
511 * Construct an encryption mapping: 540 * Construct an encryption mapping:
512 * <cipher> <key> <iv_offset> <dev_path> <start> 541 * <cipher> <key> <iv_offset> <dev_path> <start>
@@ -539,16 +568,14 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
539 568
540 key_size = strlen(argv[1]) >> 1; 569 key_size = strlen(argv[1]) >> 1;
541 570
542 cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); 571 cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
543 if (cc == NULL) { 572 if (cc == NULL) {
544 ti->error = 573 ti->error =
545 "Cannot allocate transparent encryption context"; 574 "Cannot allocate transparent encryption context";
546 return -ENOMEM; 575 return -ENOMEM;
547 } 576 }
548 577
549 cc->key_size = key_size; 578 if (crypt_set_key(cc, argv[1])) {
550 if ((!key_size && strcmp(argv[1], "-") != 0) ||
551 (key_size && crypt_decode_key(cc->key, argv[1], key_size) < 0)) {
552 ti->error = "Error decoding key"; 579 ti->error = "Error decoding key";
553 goto bad1; 580 goto bad1;
554 } 581 }
@@ -780,13 +807,14 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
780 union map_info *map_context) 807 union map_info *map_context)
781{ 808{
782 struct crypt_config *cc = (struct crypt_config *) ti->private; 809 struct crypt_config *cc = (struct crypt_config *) ti->private;
783 struct crypt_io *io = mempool_alloc(cc->io_pool, GFP_NOIO); 810 struct crypt_io *io;
784 struct convert_context ctx; 811 struct convert_context ctx;
785 struct bio *clone; 812 struct bio *clone;
786 unsigned int remaining = bio->bi_size; 813 unsigned int remaining = bio->bi_size;
787 sector_t sector = bio->bi_sector - ti->begin; 814 sector_t sector = bio->bi_sector - ti->begin;
788 unsigned int bvec_idx = 0; 815 unsigned int bvec_idx = 0;
789 816
817 io = mempool_alloc(cc->io_pool, GFP_NOIO);
790 io->target = ti; 818 io->target = ti;
791 io->bio = bio; 819 io->bio = bio;
792 io->first_clone = NULL; 820 io->first_clone = NULL;
@@ -883,14 +911,71 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
883 return 0; 911 return 0;
884} 912}
885 913
914static void crypt_postsuspend(struct dm_target *ti)
915{
916 struct crypt_config *cc = ti->private;
917
918 set_bit(DM_CRYPT_SUSPENDED, &cc->flags);
919}
920
921static int crypt_preresume(struct dm_target *ti)
922{
923 struct crypt_config *cc = ti->private;
924
925 if (!test_bit(DM_CRYPT_KEY_VALID, &cc->flags)) {
926 DMERR("aborting resume - crypt key is not set.");
927 return -EAGAIN;
928 }
929
930 return 0;
931}
932
933static void crypt_resume(struct dm_target *ti)
934{
935 struct crypt_config *cc = ti->private;
936
937 clear_bit(DM_CRYPT_SUSPENDED, &cc->flags);
938}
939
940/* Message interface
941 * key set <key>
942 * key wipe
943 */
944static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
945{
946 struct crypt_config *cc = ti->private;
947
948 if (argc < 2)
949 goto error;
950
951 if (!strnicmp(argv[0], MESG_STR("key"))) {
952 if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) {
953 DMWARN("not suspended during key manipulation.");
954 return -EINVAL;
955 }
956 if (argc == 3 && !strnicmp(argv[1], MESG_STR("set")))
957 return crypt_set_key(cc, argv[2]);
958 if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe")))
959 return crypt_wipe_key(cc);
960 }
961
962error:
963 DMWARN("unrecognised message received.");
964 return -EINVAL;
965}
966
886static struct target_type crypt_target = { 967static struct target_type crypt_target = {
887 .name = "crypt", 968 .name = "crypt",
888 .version= {1, 1, 0}, 969 .version= {1, 2, 0},
889 .module = THIS_MODULE, 970 .module = THIS_MODULE,
890 .ctr = crypt_ctr, 971 .ctr = crypt_ctr,
891 .dtr = crypt_dtr, 972 .dtr = crypt_dtr,
892 .map = crypt_map, 973 .map = crypt_map,
893 .status = crypt_status, 974 .status = crypt_status,
975 .postsuspend = crypt_postsuspend,
976 .preresume = crypt_preresume,
977 .resume = crypt_resume,
978 .message = crypt_message,
894}; 979};
895 980
896static int __init dm_crypt_init(void) 981static int __init dm_crypt_init(void)