socsvn commit: r293059 - in soc2013/def/crashdump-head: sbin sbin/cryptcore sbin/decryptcore sbin/dumpon sbin/savecore sys/amd64/amd64 sys/ddb sys/dev/null sys/geom sys/kern sys/sys

def at FreeBSD.org def at FreeBSD.org
Mon Oct 26 04:19:16 UTC 2015


Author: def
Date: Mon Oct 26 04:19:08 2015
New Revision: 293059
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=293059

Log:
  Use ioctl(2) DIOCSKERNELDUMP for EKCD setup.

Added:
  soc2013/def/crashdump-head/sbin/decryptcore/
  soc2013/def/crashdump-head/sbin/decryptcore/Makefile
  soc2013/def/crashdump-head/sbin/decryptcore/decryptcore.c
Deleted:
  soc2013/def/crashdump-head/sbin/cryptcore/
Modified:
  soc2013/def/crashdump-head/sbin/Makefile
  soc2013/def/crashdump-head/sbin/dumpon/Makefile
  soc2013/def/crashdump-head/sbin/dumpon/dumpon.c
  soc2013/def/crashdump-head/sbin/savecore/savecore.c
  soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c
  soc2013/def/crashdump-head/sys/ddb/db_textdump.c
  soc2013/def/crashdump-head/sys/dev/null/null.c
  soc2013/def/crashdump-head/sys/geom/geom_dev.c
  soc2013/def/crashdump-head/sys/kern/kern_dump.c
  soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
  soc2013/def/crashdump-head/sys/sys/conf.h
  soc2013/def/crashdump-head/sys/sys/disk.h
  soc2013/def/crashdump-head/sys/sys/kerneldump.h

Modified: soc2013/def/crashdump-head/sbin/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/Makefile	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sbin/Makefile	Mon Oct 26 04:19:08 2015	(r293059)
@@ -11,7 +11,7 @@
 	clri \
 	comcontrol \
 	conscontrol \
-	cryptcore \
+	decryptcore \
 	ddb \
 	devfs \
 	dhclient \

Added: soc2013/def/crashdump-head/sbin/decryptcore/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/def/crashdump-head/sbin/decryptcore/Makefile	Mon Oct 26 04:19:08 2015	(r293059)
@@ -0,0 +1,12 @@
+PROG=	decryptcore
+
+SRCS=	${PROG}.c
+
+LIBADD=	crypto pjdlog
+
+MAN=
+
+CFLAGS+=-I${.CURDIR}/../../sys
+CFLAGS+=-I${.CURDIR}/../../lib/libpjdlog
+
+.include <bsd.prog.mk>

Added: soc2013/def/crashdump-head/sbin/decryptcore/decryptcore.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/def/crashdump-head/sbin/decryptcore/decryptcore.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -0,0 +1,277 @@
+#include <sys/capsicum.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/kerneldump.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+
+#include <fcntl.h>
+#include <pjdlog.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+
+	pjdlog_exitx(1, "usage: decryptcore [-Lv] -p privatekey -k encryptedkey -i encryptedcore -o decryptedcore");
+}
+
+static int
+wait_for_process(pid_t pid)
+{
+	int status;
+
+	if (waitpid(pid, &status, WNOHANG | WUNTRACED | WEXITED) == -1) {
+		pjdlog_errno(LOG_ERR, "Unable to wait for a child process");
+		goto failed;
+	}
+
+	if (WIFEXITED(status))
+		return (WEXITSTATUS(status));
+failed:
+	return (1);
+}
+
+static bool
+decrypt(const char *privkeyfile, const char *keyfile, const char *input,
+    const char *output)
+{
+	uint8_t buf[2 * KERNELDUMP_BLOCK_SIZE], key[KERNELDUMP_KEY_SIZE];
+	EVP_CIPHER_CTX ctx;
+	FILE *fp;
+	struct kerneldumpkey *kdk;
+	RSA *privkey;
+	int error, ifd, kfd, ofd, olen, privkeysize;
+	ssize_t bytes, size;
+	size_t bufused, kdksize;
+	pid_t pid;
+
+	PJDLOG_ASSERT(privkeyfile != NULL);
+	PJDLOG_ASSERT(keyfile != NULL);
+	PJDLOG_ASSERT(input != NULL);
+	PJDLOG_ASSERT(output != NULL);
+
+	fp = NULL;
+	ifd = -1;
+	kdk = NULL;
+	kfd = -1;
+	ofd = -1;
+	privkey = NULL;
+
+	pid = fork();
+	if (pid == -1) {
+		pjdlog_errno(LOG_ERR, "Unable to create child process");
+		return (false);
+	}
+
+	if (pid > 0)
+		return (wait_for_process(pid) == 0);
+
+	kfd = open(keyfile, O_RDONLY);
+	if (kfd == -1) {
+		pjdlog_errno(LOG_ERR, "Unable to open %s", keyfile);
+		goto failed;
+	}
+	ifd = open(input, O_RDONLY);
+	if (ifd == -1) {
+		pjdlog_errno(LOG_ERR, "Unable to open %s", input);
+		goto failed;
+	}
+	ofd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	if (ofd == -1) {
+		pjdlog_errno(LOG_ERR, "Unable to open %s", output);
+		goto failed;
+	}
+	fp = fopen(privkeyfile, "r");
+	if (fp == NULL) {
+		pjdlog_errno(LOG_ERR, "Unable to open %s", privkeyfile);
+		goto failed;
+	}
+
+	if (cap_enter() == -1) {
+		pjdlog_errno(LOG_ERR, "Unable to enter capability mode");
+		goto failed;
+	}
+
+	privkey = RSA_new();
+	if (privkey == NULL) {
+		pjdlog_error("Unable to allocate an RSA structure. %s",
+		    ERR_error_string(ERR_get_error(), NULL));
+		goto failed;
+	}
+	EVP_CIPHER_CTX_init(&ctx);
+
+	kdksize = sizeof(*kdk);
+	kdk = calloc(1, kdksize);
+	if (kdk == NULL) {
+		pjdlog_errno(LOG_ERR, "Unable to allocate kernel dump key");
+		goto failed;
+	}
+
+	size = read(kfd, kdk, kdksize);
+	if (size == (ssize_t)kdksize) {
+		kdksize += (size_t)kdk->kdk_encryptedkeysize;
+		kdk = realloc(kdk, kdksize);
+		if (kdk == NULL) {
+			pjdlog_errno(LOG_ERR, "Unable to reallocate kernel dump key");
+			goto failed;
+		}
+		size += read(kfd, &kdk->kdk_encryptedkey,
+		    kdk->kdk_encryptedkeysize);
+	}
+	error = errno;
+	close(kfd);
+	kfd = -1;
+	if (size != (ssize_t)kdksize) {
+		errno = error;
+		pjdlog_errno(LOG_ERR, "Unable to read data from %s", keyfile);
+		goto failed;
+	}
+
+	privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL);
+	fclose(fp);
+	fp = NULL;
+	if (privkey == NULL) {
+		pjdlog_error("Unable to read data from %s.", privkeyfile);
+		goto failed;
+	}
+
+	privkeysize = RSA_size(privkey);
+	if (privkeysize != (int)kdk->kdk_encryptedkeysize) {
+		pjdlog_error("RSA modulus size mismatch: equals %db and should be %ub.",
+		    8 * privkeysize, 8 * kdk->kdk_encryptedkeysize);
+		goto failed;
+	}
+	if (RSA_private_decrypt(kdk->kdk_encryptedkeysize, kdk->kdk_encryptedkey,
+	    key, privkey, RSA_PKCS1_PADDING) != sizeof(key)) {
+		pjdlog_error("Unable to decrypt key. %s",
+		    ERR_error_string(ERR_get_error(), NULL));
+		goto failed;
+	}
+	RSA_free(privkey);
+	privkey = NULL;
+
+	EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, kdk->kdk_iv);
+	EVP_CIPHER_CTX_set_key_length(&ctx, sizeof(key));
+	EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+	bufused = 0;
+	while ((bytes = read(ifd, buf + bufused, sizeof(buf) - bufused)) > 0) {
+		bufused += bytes;
+		if (bufused != sizeof(buf))
+			continue;
+
+		if (EVP_DecryptUpdate(&ctx, buf, &olen, buf,
+		    sizeof(buf)) == 0) {
+			pjdlog_error("Unable to decrypt core.");
+			goto failed;
+		}
+		PJDLOG_ASSERT(olen == (int)sizeof(buf));
+
+		if (write(ofd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) {
+			pjdlog_errno(LOG_ERR, "Unable to write data to %s",
+			    output);
+			goto failed;
+		}
+		bufused = 0;
+	}
+	if (bytes < 0) {
+		pjdlog_errno(LOG_ERR, "Unable to read data from %s", input);
+		goto failed;
+	}
+
+	close(ofd);
+	close(ifd);
+	bzero(key, sizeof(key));
+	bzero(buf, sizeof(buf));
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	free(kdk);
+	exit(0);
+failed:
+	if (ofd >= 0)
+		close(ofd);
+	if (ifd >= 0)
+		close(kfd);
+	if (kfd >= 0)
+		close(kfd);
+	if (fp != NULL)
+		fclose(fp);
+	bzero(key, sizeof(key));
+	bzero(buf, sizeof(buf));
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	free(kdk);
+	RSA_free(privkey);
+	exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+	const char *input, *keyfile, *output, *rsakeyfile;
+	int debug;
+	char ch;
+	bool usesyslog;
+
+	pjdlog_init(PJDLOG_MODE_STD);
+	pjdlog_prefix_set("(decryptcore) ");
+
+	debug = 0;
+	rsakeyfile = NULL;
+	usesyslog = false;
+	while ((ch = getopt(argc, argv, "Li:k:o:p:v")) != -1) {
+		switch (ch) {
+		case 'L':
+			usesyslog = true;
+			break;
+		case 'i':
+			input = optarg;
+			break;
+		case 'k':
+			keyfile = optarg;
+			break;
+		case 'o':
+			output = optarg;
+			break;
+		case 'p':
+			rsakeyfile = optarg;
+			break;
+		case 'v':
+			debug++;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0)
+		usage();
+	if (input == NULL || keyfile == NULL || output == NULL ||
+	    rsakeyfile == NULL) {
+		usage();
+	}
+
+	if (usesyslog)
+		pjdlog_mode_set(PJDLOG_MODE_SYSLOG);
+	pjdlog_debug_set(debug);
+
+	if (!decrypt(rsakeyfile, keyfile, input, output)) {
+		if (unlink(output) != 0)
+			pjdlog_exit(1, "Unable to remove output");
+		exit(1);
+	}
+
+	pjdlog_fini();
+
+	return (0);
+}

Modified: soc2013/def/crashdump-head/sbin/dumpon/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/dumpon/Makefile	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sbin/dumpon/Makefile	Mon Oct 26 04:19:08 2015	(r293059)
@@ -1,6 +1,9 @@
 # $FreeBSD$
 
 PROG=	dumpon
+
+LIBADD=	crypto
+
 MAN=	dumpon.8
 
 .include <bsd.prog.mk>

Modified: soc2013/def/crashdump-head/sbin/dumpon/dumpon.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/dumpon/dumpon.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sbin/dumpon/dumpon.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -41,10 +41,16 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/capsicum.h>
 #include <sys/param.h>
 #include <sys/disk.h>
 #include <sys/sysctl.h>
 
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+#include <assert.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -62,7 +68,7 @@
 usage(void)
 {
 	fprintf(stderr, "%s\n%s\n%s\n",
-	    "usage: dumpon [-v] special_file",
+	    "usage: dumpon [-v] [-k public_key] special_file",
 	    "       dumpon [-v] off",
 	    "       dumpon [-v] -l");
 	exit(EX_USAGE);
@@ -95,6 +101,71 @@
 }
 
 static void
+genkey(const char *pubkeyfile, struct diocskerneldump_arg *kda)
+{
+	FILE *fp;
+	RSA *pubkey;
+
+	assert(pubkeyfile != NULL);
+	assert(kda != NULL);
+
+	fp = NULL;
+	pubkey = NULL;
+
+	fp = fopen(pubkeyfile, "r");
+	if (fp == NULL) {
+		warn("Unable to open %s", pubkeyfile);
+		goto failed;
+	}
+
+	if (cap_enter() == -1) {
+		warn("Unable to enter capability mode");
+		goto failed;
+	}
+
+	pubkey = RSA_new();
+	if (pubkey == NULL) {
+		warnx("Unable to allocate an RSA structure. %s",
+		    ERR_error_string(ERR_get_error(), NULL));
+		goto failed;
+	}
+
+	pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL);
+	fclose(fp);
+	fp = NULL;
+	if (pubkey == NULL) {
+		warnx("Unable to read data from %s.", pubkeyfile);
+		goto failed;
+	}
+
+	kda->kda_encryptedkeysize = RSA_size(pubkey);
+	kda->kda_encryptedkey = calloc(1, kda->kda_encryptedkeysize);
+	if (kda->kda_encryptedkey == NULL) {
+		warn("Unable to allocate encrypted key");
+		goto failed;
+	}
+
+	arc4random_buf(kda->kda_key, sizeof(kda->kda_key));
+	if (RSA_public_encrypt(sizeof(kda->kda_key), kda->kda_key,
+	    kda->kda_encryptedkey, pubkey,
+	    RSA_PKCS1_PADDING) != (int)kda->kda_encryptedkeysize) {
+		warn("Unable to encrypt the one-time key");
+		goto failed;
+	}
+	RSA_free(pubkey);
+	pubkey = NULL;
+
+	kda->kda_encrypt = 1;
+	return;
+failed:
+	if (fp != NULL)
+		fclose(fp);
+	free(kda->kda_encryptedkey);
+	RSA_free(pubkey);
+	exit(1);
+}
+
+static void
 listdumpdev(void)
 {
 	char dumpdev[PATH_MAX];
@@ -123,13 +194,20 @@
 int
 main(int argc, char *argv[])
 {
+	struct diocskerneldump_arg kda;
+	const char *pubkeyfile;
 	int ch;
 	int i, fd;
-	u_int u;
 	int do_listdumpdev = 0;
 
-	while ((ch = getopt(argc, argv, "lv")) != -1)
+	bzero(&kda, sizeof(kda));
+	pubkeyfile = NULL;
+
+	while ((ch = getopt(argc, argv, "k:lv")) != -1)
 		switch((char)ch) {
+		case 'k':
+			pubkeyfile = optarg;
+			break;
 		case 'l':
 			do_listdumpdev = 1;
 			break;
@@ -156,18 +234,22 @@
 		if (fd < 0)
 			err(EX_OSFILE, "%s", argv[0]);
 		check_size(fd, argv[0]);
-		u = 0;
-		i = ioctl(fd, DIOCSKERNELDUMP, &u);
-		u = 1;
-		i = ioctl(fd, DIOCSKERNELDUMP, &u);
+		kda.kda_enable = 0;
+		i = ioctl(fd, DIOCSKERNELDUMP, &kda);
+		if (pubkeyfile != NULL)
+			genkey(pubkeyfile, &kda);
+		kda.kda_enable = 1;
+		i = ioctl(fd, DIOCSKERNELDUMP, &kda);
+		free(kda.kda_encryptedkey);
+		bzero(&kda, sizeof(kda));
 		if (i == 0 && verbose)
 			printf("kernel dumps on %s\n", argv[0]);
 	} else {
 		fd = open(_PATH_DEVNULL, O_RDONLY);
 		if (fd < 0)
 			err(EX_OSFILE, "%s", _PATH_DEVNULL);
-		u = 0;
-		i = ioctl(fd, DIOCSKERNELDUMP, &u);
+		kda.kda_enable = 0;
+		i = ioctl(fd, DIOCSKERNELDUMP, &kda);
 		if (i == 0 && verbose)
 			printf("kernel dumps disabled\n");
 	}

Modified: soc2013/def/crashdump-head/sbin/savecore/savecore.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/savecore.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sbin/savecore/savecore.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -185,7 +185,7 @@
 }
 
 static bool
-writekey(const char *keyname, struct kerneldumpkey *kdk)
+writekey(const char *keyname, uint8_t *dumpkey, uint32_t dumpkeysize)
 {
 	int fd;
 
@@ -195,8 +195,7 @@
 		return (false);
 	}
 
-	if (write(fd, kdk, kerneldumpkey_size(kdk)) !=
-	    (ssize_t)kerneldumpkey_size(kdk)) {
+	if (write(fd, dumpkey, dumpkeysize) != (ssize_t)dumpkeysize) {
 		syslog(LOG_ERR, "Unable to write the key to %s.", keyname);
 		close(fd);
 		return (false);
@@ -457,12 +456,12 @@
 static void
 DoFile(const char *savedir, const char *device)
 {
-	struct kerneldumpkey *kdk;
 	xo_handle_t *xostdout, *xoinfo;
 	static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX];
 	static char keyname[PATH_MAX];
 	static char *buf = NULL;
 	struct kerneldumpheader kdhf, kdhl;
+	uint8_t *dumpkey;
 	off_t mediasize, dumpsize, firsthd, lasthd;
 	FILE *info, *fp;
 	mode_t oumask;
@@ -709,24 +708,24 @@
 	isencrypted = false;
 	if (dumpkeysize > 0) {
 		isencrypted = true;
-		kdk = (struct kerneldumpkey *)calloc(1, dumpkeysize);
-		if (kdk == NULL) {
+		dumpkey = calloc(1, dumpkeysize);
+		if (dumpkey == NULL) {
 			syslog(LOG_ERR, "Unable to allocate kernel dump key.");
 			nerr++;
 			goto closefd;
 		}
 
-		error = read(fd, kdk, dumpkeysize);
+		error = read(fd, dumpkey, dumpkeysize);
 		if (error != (int)dumpkeysize) {
 			syslog(LOG_ERR, "Unable to read kernel dump key.");
 			nerr++;
-			goto closefd;
+			goto closeall;
 		}
 
 		snprintf(keyname, sizeof(keyname), "key.%d", bounds);
-		if (!writekey(keyname, kdk)) {
+		if (!writekey(keyname, dumpkey, dumpkeysize)) {
 			nerr++;
-			goto closefd;
+			goto closeall;
 		}
 	}
 

Modified: soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c
==============================================================================
--- soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -321,13 +321,13 @@
 
 	/* Determine dump offset on device. */
 	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2 +
-	    kerneldumpkey_size(di->kdk)) {
+	    kerneldumpcrypto_dumpkeysize(di->kdc)) {
 		error = E2BIG;
 		goto fail;
 	}
 	dumplo = di->mediaoffset + di->mediasize - dumpsize;
 	dumplo -= sizeof(kdh) * 2;
-	dumplo -= kerneldumpkey_size(di->kdk);
+	dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc);
 	progress = dumpsize;
 
 	/* Initialize mdhdr */
@@ -342,7 +342,7 @@
 	mdhdr.dmapend = DMAP_MAX_ADDRESS;
 
 	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, dumpsize,
-	    kerneldumpkey_size(di->kdk), di->blocksize);
+	    kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize);
 
 	printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20,
 	    ptoa((uintmax_t)physmem) / 1048576);
@@ -354,10 +354,10 @@
 	dumplo += sizeof(kdh);
 
 	/* Dump key */
-	error = dump_write_key(di, di->kdk, 0, dumplo);
+	error = dump_write_key(di, 0, dumplo);
 	if (error)
 		goto fail;
-	dumplo += kerneldumpkey_size(di->kdk);
+	dumplo += kerneldumpcrypto_dumpkeysize(di->kdc);
 
 	/* Dump my header */
 	bzero(&fakepd, sizeof(fakepd));

Modified: soc2013/def/crashdump-head/sys/ddb/db_textdump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/ddb/db_textdump.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/ddb/db_textdump.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -427,7 +427,7 @@
 void
 textdump_dumpsys(struct dumperinfo *di)
 {
-	struct kerneldumpkey *kdk;
+	struct kerneldumpcrypto *kdc;
 	off_t dumplen, trailer_offset;
 
 	if (di->blocksize != TEXTDUMP_BLOCKSIZE) {
@@ -452,8 +452,8 @@
 	/*
 	 * Disable EKCD because we don't provide encrypted textdumps.
 	 */
-	kdk = di->kdk;
-	di->kdk = NULL;
+	kdc = di->kdc;
+	di->kdc = NULL;
 
 	/*
 	 * Position the start of the dump so that we'll write the kernel dump
@@ -511,7 +511,7 @@
 	/*
 	 * Restore EKCD status.
 	 */
-	di->kdk = kdk;
+	di->kdc = kdc;
 }
 
 /*-

Modified: soc2013/def/crashdump-head/sys/dev/null/null.c
==============================================================================
--- soc2013/def/crashdump-head/sys/dev/null/null.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/dev/null/null.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -109,7 +109,7 @@
 
 	switch (cmd) {
 	case DIOCSKERNELDUMP:
-		error = set_dumper(NULL, NULL, td);
+		error = set_dumper(NULL, NULL, td, 0, NULL, 0, NULL);
 		break;
 	case FIONBIO:
 		break;

Modified: soc2013/def/crashdump-head/sys/geom/geom_dev.c
==============================================================================
--- soc2013/def/crashdump-head/sys/geom/geom_dev.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/geom/geom_dev.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -127,26 +127,32 @@
 }
 
 static int
-g_dev_setdumpdev(struct cdev *dev, struct thread *td)
+g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda,
+    struct thread *td)
 {
 	struct g_kerneldump kd;
 	struct g_consumer *cp;
 	int error, len;
 
 	if (dev == NULL)
-		return (set_dumper(NULL, NULL, td));
+		return (set_dumper(NULL, NULL, td, 0, NULL, 0, NULL));
 
 	cp = dev->si_drv2;
 	len = sizeof(kd);
 	kd.offset = 0;
 	kd.length = OFF_MAX;
 	error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd);
-	if (error == 0) {
-		error = set_dumper(&kd.di, devtoname(dev), td);
-		if (error == 0)
-			dev->si_flags |= SI_DUMPDEV;
-	}
-	return (error);
+	if (error != 0)
+		return (error);
+
+	error = set_dumper(&kd.di, devtoname(dev), td, kda->kda_encrypt,
+	    kda->kda_key, kda->kda_encryptedkeysize,
+	    kda->kda_encryptedkey);
+	if (error != 0)
+		return (error);
+
+	dev->si_flags |= SI_DUMPDEV;
+	return (0);
 }
 
 static void
@@ -157,7 +163,7 @@
 		return;
 	if (strcmp(devtoname(dev), dumpdev) != 0)
 		return;
-	if (g_dev_setdumpdev(dev, curthread) == 0) {
+	if (g_dev_setdumpdev(dev, NULL, curthread) == 0) {
 		freeenv(dumpdev);
 		dumpdev = NULL;
 	}
@@ -459,12 +465,15 @@
 	case DIOCGFRONTSTUFF:
 		error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
 		break;
-	case DIOCSKERNELDUMP:
-		if (*(u_int *)data == 0)
-			error = g_dev_setdumpdev(NULL, td);
+	case DIOCSKERNELDUMP: {
+		struct diocskerneldump_arg *kda;
+		kda = (struct diocskerneldump_arg *)data;
+		if (kda->kda_enable == 0)
+			error = g_dev_setdumpdev(NULL, NULL, td);
 		else
-			error = g_dev_setdumpdev(dev, td);
+			error = g_dev_setdumpdev(dev, kda, td);
 		break;
+	}
 	case DIOCGFLUSH:
 		error = g_io_flush(cp);
 		break;
@@ -681,7 +690,7 @@
 
 	/* Reset any dump-area set on this device */
 	if (dev->si_flags & SI_DUMPDEV)
-		(void)set_dumper(NULL, NULL, curthread);
+		(void)set_dumper(NULL, NULL, curthread, 0, NULL, 0, NULL);
 
 	/* Destroy the struct cdev *so we get no more requests */
 	destroy_dev_sched_cb(dev, g_dev_callback, cp);

Modified: soc2013/def/crashdump-head/sys/kern/kern_dump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_dump.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/kern/kern_dump.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -349,16 +349,16 @@
 
 	/* Determine dump offset on device. */
 	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2 +
-	    kerneldumpkey_size(di->kdk)) {
+	    kerneldumpcrypto_dumpkeysize(di->kdc)) {
 		error = ENOSPC;
 		goto fail;
 	}
 	dumplo = di->mediaoffset + di->mediasize - dumpsize;
 	dumplo -= sizeof(kdh) * 2;
-	dumplo -= kerneldumpkey_size(di->kdk);
+	dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc);
 
 	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize,
-	    kerneldumpkey_size(di->kdk), di->blocksize);
+	    kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize);
 
 	printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20,
 	    ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS);
@@ -370,10 +370,10 @@
 	dumplo += sizeof(kdh);
 
 	/* Dump key */
-	error = dump_write_key(di, di->kdk, 0, dumplo);
+	error = dump_write_key(di, 0, dumplo);
 	if (error)
 		goto fail;
-	dumplo += kerneldumpkey_size(di->kdk);
+	dumplo += kerneldumpcrypto_dumpkeysize(di->kdc);
 
 	/* Dump ELF header */
 	error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr));

Modified: soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Mon Oct 26 04:19:08 2015	(r293059)
@@ -144,29 +144,18 @@
 #ifdef EKCD
 FEATURE(ekcd, "Encrypted kernel crash dumps support");
 
-MALLOC_DEFINE(M_KDK, "kerneldumpkey", "Kernel dump key structure");
+MALLOC_DEFINE(M_EKCD, "ekcd", "Encrypted kernel crash dumps data");
 
-static struct kerneldumpcrypto {
-	uint8_t		kdc_key[KERNELDUMP_KEY_SIZE];
+struct kerneldumpcrypto {
+	uint8_t		kdc_algorithm;
 	uint8_t		kdc_iv[KERNELDUMP_IV_SIZE];
 	keyInstance	kdc_ki;
 	cipherInstance	kdc_ci;
 	off_t		kdc_nextoffset;
-} dumpcrypto;
-
-static struct kerneldumpkey *dumpkey;
-
-static int kerneldump_sysctl_enable(SYSCTL_HANDLER_ARGS);
-static int kerneldump_sysctl_setup(SYSCTL_HANDLER_ARGS);
-
-SYSCTL_NODE(_security, OID_AUTO, ekcd, CTLFLAG_RW, 0,
-    "Encrypted kernel crash dumps");
-
-SYSCTL_PROC(_security_ekcd, OID_AUTO, enable, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
-    kerneldump_sysctl_enable, "I", "Enable encrypted kernel crash dumps");
-
-SYSCTL_PROC(_security_ekcd, OID_AUTO, setup, CTLTYPE_OPAQUE | CTLFLAG_WR, NULL,
-    0, kerneldump_sysctl_setup, "", "Setup");
+	uint8_t		kdc_dumpkeysize;
+	uint32_t	kdc_encryptedkeysize;
+	uint8_t		kdc_encryptedkey[];
+};
 #endif /* EKCD */
 
 /*
@@ -854,108 +843,66 @@
 		printf("done\n");
 }
 
+static char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)];
+SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
+    dumpdevname, 0, "Device for kernel dumps");
+
 #ifdef EKCD
-static int
-kerneldump_crypto_init(struct dumperinfo *di, struct kerneldumpcrypto *kdc,
-    struct kerneldumpkey *kdk)
+static struct kerneldumpcrypto *
+kerneldumpcrypto_create(uint8_t *key, uint32_t encryptedkeysize,
+    uint8_t *encryptedkey)
 {
+	struct kerneldumpcrypto *kdc;
 	int error;
 
+	kdc = malloc(sizeof(*kdc) + encryptedkeysize, M_EKCD,
+	    M_WAITOK | M_ZERO);
+
+	kdc->kdc_algorithm = CRYPTO_AES_CBC;
 	error = rijndael_makeKey(&kdc->kdc_ki, DIR_ENCRYPT,
-	    8 * KERNELDUMP_KEY_SIZE, kdc->kdc_key);
+	    8 * KERNELDUMP_KEY_SIZE, key);
+	bzero(key, KERNELDUMP_KEY_SIZE);
 	if (error <= 0)
-		return (EINVAL);
+		goto failed;
 
+	arc4rand(kdc->kdc_iv, sizeof(kdc->kdc_iv), 0);
 	error = rijndael_cipherInit(&kdc->kdc_ci, MODE_CBC, kdc->kdc_iv);
 	if (error <= 0)
-		return (EINVAL);
-
-	kdc->kdc_nextoffset = 0;
+		goto failed;
 
-	di->kdc = kdc;
-	di->kdk = kdk;
+	kdc->kdc_encryptedkeysize = encryptedkeysize;
+	bcopy(encryptedkey, kdc->kdc_encryptedkey, kdc->kdc_encryptedkeysize);
 
-	return (0);
-}
-
-static int
-kerneldump_sysctl_enable(SYSCTL_HANDLER_ARGS)
-{
-	int enable, error;
-
-	if (dumper.kdk != NULL)
-		enable = 1;
-	else
-		enable = 0;
-
-	error = sysctl_handle_opaque(oidp, &enable, sizeof(enable), req);
-	if (error != 0)
-		return (error);
-
-	if (enable == 0) {
-		free(dumpkey, M_KDK);
-		dumpkey = NULL;
-		dumper.kdk = NULL;
-	}
-
-	return (0);
+	kdc->kdc_nextoffset = 0;
+	kdc->kdc_dumpkeysize = (sizeof(kdc->kdc_algorithm) +
+	    sizeof(kdc->kdc_iv) + sizeof(kdc->kdc_encryptedkeysize) +
+	    kdc->kdc_encryptedkeysize + KERNELDUMP_BLOCK_SIZE - 1) /
+	    KERNELDUMP_BLOCK_SIZE * KERNELDUMP_BLOCK_SIZE;
+	kdc->kdc_dumpkeysize = (sizeof(struct kerneldumpkey) +
+	    kdc->kdc_encryptedkeysize + KERNELDUMP_BLOCK_SIZE - 1) /
+	    KERNELDUMP_BLOCK_SIZE * KERNELDUMP_BLOCK_SIZE;
+
+	return (kdc);
+failed:
+	free(kdc, M_EKCD);
+	return (NULL);
 }
+#endif /* EKCD */
 
-static int
-kerneldump_sysctl_setup(SYSCTL_HANDLER_ARGS)
+uint32_t
+kerneldumpcrypto_dumpkeysize(const struct kerneldumpcrypto *kdc)
 {
-	struct kerneldumpsetup kds;
-	struct kerneldumpkey *kdk;
-	size_t kdksize;
-	int error;
-
-	if (req->newptr == NULL)
-		return (EPERM);
-
-	error = sysctl_handle_opaque(oidp, &kds, sizeof(kds), req);
-	if (error != 0)
-		return (error);
 
-	bcopy(kds.kds_key, dumpcrypto.kdc_key, sizeof(dumpcrypto.kdc_key));
-	bzero(kds.kds_key, sizeof(kds.kds_key));
-	arc4rand(dumpcrypto.kdc_iv, sizeof(dumpcrypto.kdc_iv), 0);
-
-	kdksize = ((sizeof(*kdk) + kds.kds_encryptedkeylen +
-	    KERNELDUMP_BLOCK_SIZE - 1) / KERNELDUMP_BLOCK_SIZE) *
-	    KERNELDUMP_BLOCK_SIZE;
-	kdk = malloc(kdksize, M_KDK, M_WAITOK | M_ZERO);
-	kdk->kdk_size = kdksize;
-	kdk->kdk_algorithm = CRYPTO_AES_CBC;
-	kdk->kdk_keysize = KERNELDUMP_KEY_SIZE;
-	bcopy(dumpcrypto.kdc_iv, kdk->kdk_iv, sizeof(kdk->kdk_iv));
-	kdk->kdk_encryptedkeylen = kds.kds_encryptedkeylen;
-
-	error = sysctl_handle_opaque(oidp, kdk->kdk_encryptedkey,
-	    kdk->kdk_encryptedkeylen, req);
-	if (error != 0) {
-		free(kdk, M_KDK);
-		return (error);
-	}
-
-	error = kerneldump_crypto_init(&dumper, &dumpcrypto, kdk);
-	if (error != 0) {
-		free(kdk, M_KDK);
-		return (error);
-	}
-
-	free(dumpkey, M_KDK);
-	dumpkey = kdk;
-	return (0);
+	if (kdc == NULL)
+		return (0);
+	return (kdc->kdc_dumpkeysize);
 }
-#endif /* EKCD */
-
-static char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)];
-SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
-    dumpdevname, 0, "Device for kernel dumps");
 
 /* Registration of dumpers */
 int
-set_dumper(struct dumperinfo *di, const char *devname, struct thread *td)
+set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
+    uint8_t encrypt, uint8_t *key, uint32_t encryptedkeysize,
+    uint8_t *encryptedkey)
 {
 	size_t wantcopy;
 	int error;
@@ -965,6 +912,7 @@
 		return (error);
 
 	if (di == NULL) {
+		free(dumper.kdc, M_EKCD);
 		bzero(&dumper, sizeof dumper);
 		dumpdevname[0] = '\0';
 		return (0);
@@ -973,12 +921,14 @@
 		return (EBUSY);
 	dumper = *di;
 	dumper.kdc = NULL;
-	dumper.kdk = NULL;
 
 #ifdef EKCD
-	error = kerneldump_crypto_init(&dumper, &dumpcrypto, dumpkey);
-	if (error != 0)
-		return (error);
+	if (encrypt == 1) {
+		dumper.kdc = kerneldumpcrypto_create(key, encryptedkeysize,
+		    encryptedkey);
+		if (dumper.kdc == NULL)
+			return (EINVAL);
+	}
 #endif
 
 	wantcopy = strlcpy(dumpdevname, devname, sizeof(dumpdevname));
@@ -986,6 +936,7 @@
 		printf("set_dumper: device name truncated from '%s' -> '%s'\n",
 			devname, dumpdevname);
 	}
+
 	return (0);
 }
 
@@ -1090,7 +1041,7 @@
 {
 
 #ifdef EKCD
-	if (di->kdk != NULL) {
+	if (di->kdc != NULL) {
 		return (dump_encrypted_write(di, virtual, physical, offset,
 		    length));
 	}
@@ -1108,12 +1059,26 @@
 }
 
 int
-dump_write_key(struct dumperinfo *di, struct kerneldumpkey *kdk,
-    vm_offset_t physical, off_t offset)
+dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset)
 {
+	struct kerneldumpcrypto *kdc;
+	struct kerneldumpkey *kdk;
+	int ret;
+
+	kdc = di->kdc;
+	if (kdc == NULL)
+		return (0);
 
-	return (dump_raw_write(di, kdk, physical, offset,
-	    kerneldumpkey_size(kdk)));
+	kdk = malloc(kdc->kdc_dumpkeysize, M_EKCD, M_WAITOK | M_ZERO);
+	kdk->kdk_algorithm = kdc->kdc_algorithm;
+	bcopy(kdc->kdc_iv, kdk->kdk_iv, sizeof(kdk->kdk_iv));
+	kdk->kdk_encryptedkeysize = kdc->kdc_encryptedkeysize;
+	bcopy(kdc->kdc_encryptedkey, kdk->kdk_encryptedkey,
+	    kdk->kdk_encryptedkeysize);
+
+	ret = dump_raw_write(di, kdk, physical, offset, kdc->kdc_dumpkeysize);
+	free(kdk, M_EKCD);
+	return (ret);
 }
 
 void

Modified: soc2013/def/crashdump-head/sys/sys/conf.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/conf.h	Mon Oct 26 03:55:13 2015	(r293058)
+++ soc2013/def/crashdump-head/sys/sys/conf.h	Mon Oct 26 04:19:08 2015	(r293059)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-soc-all mailing list