socsvn commit: r257635 - in soc2013/def/crashdump-head: etc/rc.d sbin/dumpkey

def at FreeBSD.org def at FreeBSD.org
Mon Sep 23 04:40:35 UTC 2013


Author: def
Date: Mon Sep 23 04:40:34 2013
New Revision: 257635
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257635

Log:
  Change dumpkey to decrypt a crash dump with a custom XTS-AES key and a RSA key.

Modified:
  soc2013/def/crashdump-head/etc/rc.d/dumpkey
  soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c

Modified: soc2013/def/crashdump-head/etc/rc.d/dumpkey
==============================================================================
--- soc2013/def/crashdump-head/etc/rc.d/dumpkey	Mon Sep 23 04:20:37 2013	(r257634)
+++ soc2013/def/crashdump-head/etc/rc.d/dumpkey	Mon Sep 23 04:40:34 2013	(r257635)
@@ -29,7 +29,7 @@
 
 dumpkey_start()
 {
-	/sbin/dumpkey -p ${dumpkey_pub}
+	/sbin/dumpkey -e ${dumpkey_pub}
 }
 
 dumpkey_predecrypt()

Modified: soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c	Mon Sep 23 04:20:37 2013	(r257634)
+++ soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c	Mon Sep 23 04:40:34 2013	(r257635)
@@ -13,6 +13,7 @@
 #include <openssl/pem.h>
 
 #define	PATH_DEVRANDOM		"/dev/random"
+#define	PEFS_SECTOR_SIZE	4096
 
 static void
 hkdf_expand(struct xts_ctx *ctx, const uint8_t *masterkey, uint8_t *key,
@@ -31,15 +32,17 @@
 static void
 usage(void)
 {
-	printf("usage: dumpkey -p public_key\n");
+	printf("%s\n%s\n",
+		"usage: dumpkey -e public_key",
+		"       dumpkey -d private_key -k encrypted_key -c encrypted_core");
 }
 
 static int
-random_data(char *buf, size_t size)
+read_data(char *buf, size_t size, char *fname)
 {
 	FILE *fp;
 
-	fp = fopen(PATH_DEVRANDOM, "r");
+	fp = fopen(fname, "r");
 
 	if (fp == NULL)
 		return (-1);
@@ -56,6 +59,12 @@
 }
 
 static int
+random_data(char *buf, size_t size)
+{
+	return (read_data(buf, size, PATH_DEVRANDOM));
+}
+
+static int
 encrypt_key(char *plainkey, struct kerneldumpkey *key, RSA *public_key, char *public_key_file)
 {
 	FILE *fp;
@@ -83,6 +92,33 @@
 }
 
 static int
+decrypt_key(char *cipherkey, char *key, char *tweak, RSA *private_key, char *private_key_file)
+{
+	FILE *fp;
+	char buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE];
+
+	fp = fopen(private_key_file, "r");
+
+	if (fp == NULL)
+		return (-1);
+
+	private_key = PEM_read_RSAPrivateKey(fp, &private_key, NULL, NULL);
+	fclose(fp);
+
+	if (private_key == NULL)
+		return (-1);
+
+	if (RSA_private_decrypt(KERNELDUMP_ENCRYPTED_KEY_SIZE, cipherkey, buf,
+		private_key, RSA_PKCS1_PADDING) == -1)
+		return (-1);
+
+	memcpy(key, buf, KERNELDUMP_KEY_SIZE);
+	memcpy(tweak, buf + KERNELDUMP_KEY_SIZE, KERNELDUMP_TWEAK_SIZE);
+
+	return (0);
+}
+
+static int
 expand_key(char *masterkey, struct xts_ctx *data_ctx, struct xts_ctx *tweak_ctx)
 {
 	struct xts_ctx ctx;
@@ -111,74 +147,165 @@
 	return (sysctlbyname("kern.dumpkey", NULL, NULL, key, sizeof(struct kerneldumpkey)));
 }
 
-int
-main(int argc, char **argv)
+static void
+generate_key(char *public_key_file)
 {
+	char buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE];
 	struct kerneldumpkey key;
-	char *public_key_file, buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE];
-	int ch, error;
 	RSA *public_key;
 
-	ERR_load_crypto_strings();
-	OpenSSL_add_all_algorithms();
-	OPENSSL_config(NULL);
-
-	error = 0;
-	public_key_file = NULL;
 	public_key = RSA_new();
 
-	while ((ch = getopt(argc, argv, "p:")) != -1)
-		switch (ch) {
-		case 'p':
-			public_key_file = optarg;
-			break;
-		default:
-			usage();
-			error = 1;
-			goto out;
-		}
-
-	if (public_key_file == NULL) {
-		usage();
-		error = 1;
-		goto out;
-	}
-
 	if (random_data(buf, KERNELDUMP_KEY_SIZE)) {
 		printf("Error: cannot generate a symmetric key.\n");
-		error = 1;
 		goto out;
 	}
 
 	if (random_data(key.tweak, KERNELDUMP_TWEAK_SIZE)) {
 		printf("Error: cannot generate a tweak.\n");
-		error = 1;
 		goto out;
 	}
 
 	if (expand_key(buf, &key.data_ctx, &key.tweak_ctx)) {
-		printf("Error: cannot expand a symmetric key.");
-		error = 1;
+		printf("Error: cannot expand a symmetric key.\n");
 		goto out;
 	}
 
 	if (encrypt_key(buf, &key, public_key, public_key_file)) {
-		printf("Error: cannot encrypt a symmetric key.\n");
-		error = 1;
+		printf("Error: cannot encrypt a key.\n");
 		goto out;
 	}
 
 	if (sysctl_dumpkey(&key)) {
 		printf("Error: cannot set a kernel crash dump key.\n");
-		error = 1;
 		goto out;
 	}
 
 out:
 	bzero(&key, sizeof(struct kerneldumpkey));
-	bzero(buf, KERNELDUMP_KEY_SIZE);
+	bzero(buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE);
 	RSA_free(public_key);
+}
+
+static void
+decrypt_core(char *encrypted_core, char *private_key_file, char *encrypted_key_file)
+{
+	char key[KERNELDUMP_KEY_SIZE], tweak[KERNELDUMP_TWEAK_SIZE];
+	char buf[PEFS_SECTOR_SIZE];
+	struct xts_ctx data_ctx, tweak_ctx;
+	RSA *private_key;
+	int buf_used, offset;
+	size_t bytes;
+	FILE *fp, *fp_w;
+
+	private_key = RSA_new();
+
+	memcpy(buf, encrypted_core, strlen(encrypted_core) + 1);
+	strcat(buf, "-decrypted");
 
+	fp = fopen(encrypted_core, "r");
+	fp_w = fopen(buf, "w");
+
+	if (fp == NULL || fp_w == NULL)
+		goto out;
+
+	if (read_data(buf, KERNELDUMP_ENCRYPTED_KEY_SIZE, encrypted_key_file)) {
+		printf("Error: cannot read an encrypted key.\n");
+		goto out;
+	}
+
+	if (decrypt_key(buf, key, tweak, private_key, private_key_file)) {
+		printf("Error: cannot decrypt a key.\n");
+		goto out;
+	}
+
+	if (expand_key(key, &data_ctx, &tweak_ctx)) {
+		printf("Error: cannot expand a symmetric key.\n");
+		goto out;
+	}
+
+	offset = buf_used = 0;
+	do {
+		bytes = fread(buf + buf_used, 1, PEFS_SECTOR_SIZE - buf_used, fp);
+		buf_used += bytes;
+
+		if (buf_used == PEFS_SECTOR_SIZE || (buf_used > 0 && bytes == 0)) {
+			xts_block_decrypt(&xts_alg_aes, &tweak_ctx, &data_ctx, offset, tweak, 0, buf_used, buf, buf);
+
+			if (fwrite(buf, 1, buf_used, fp_w) != buf_used)
+				goto out;
+
+			offset += buf_used;
+			buf_used = 0;
+		}
+	} while (bytes > 0);
+
+out:
+	fclose(fp_w);
+	fclose(fp);
+	bzero(&buf, sizeof(buf));
+	bzero(&key, sizeof(key));
+	bzero(&tweak, sizeof(tweak));
+	bzero(&data_ctx, sizeof(struct xts_ctx));
+	bzero(&tweak_ctx, sizeof(struct xts_ctx));
+	RSA_free(private_key);
+}
+
+int
+main(int argc, char **argv)
+{
+	char *public_key_file, *private_key_file, *encrypted_key_file, *encrypted_core;
+	int ch, error;
+
+	ERR_load_crypto_strings();
+	OpenSSL_add_all_algorithms();
+	OPENSSL_config(NULL);
+
+	error = 0;
+	public_key_file = private_key_file = NULL;
+	encrypted_key_file = encrypted_core = NULL;
+
+	while ((ch = getopt(argc, argv, "c:d:e:k:")) != -1)
+		switch (ch) {
+		case 'c':
+			encrypted_core = optarg;
+			break;
+		case 'd':
+			private_key_file = optarg;
+			break;
+		case 'e':
+			public_key_file = optarg;
+			break;
+		case 'k':
+			encrypted_key_file = optarg;
+			break;
+		default:
+			usage();
+			error = 1;
+			goto out;
+		}
+
+	if ((public_key_file == NULL && private_key_file == NULL) ||
+		(public_key_file != NULL && private_key_file != NULL)) {
+		usage();
+		error = 1;
+		goto out;
+	}
+
+	if (private_key_file != NULL && (encrypted_key_file == NULL ||
+		encrypted_core == NULL)) {
+		usage();
+		error = 1;
+		goto out;
+	}
+
+	if (public_key_file != NULL)
+		generate_key(public_key_file);
+
+	if (private_key_file != NULL)
+		decrypt_core(encrypted_core, private_key_file, encrypted_key_file);
+
+out:
 	ERR_free_strings();
 	EVP_cleanup();
 


More information about the svn-soc-all mailing list