socsvn commit: r284780 - in soc2013/def/crashdump-head: etc/defaults etc/rc.d sbin sbin/cryptcore sbin/dumpkey sbin/savecore sys/amd64/conf sys/conf sys/kern sys/sys

def at FreeBSD.org def at FreeBSD.org
Wed Apr 29 09:35:04 UTC 2015


Author: def
Date: Wed Apr 29 09:34:58 2015
New Revision: 284780
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=284780

Log:
  Integrate EKCD changes.

Added:
  soc2013/def/crashdump-head/sbin/cryptcore/
  soc2013/def/crashdump-head/sbin/cryptcore/Makefile
  soc2013/def/crashdump-head/sbin/cryptcore/cryptcore.c
Deleted:
  soc2013/def/crashdump-head/etc/rc.d/dumpkey
  soc2013/def/crashdump-head/sbin/dumpkey/
  soc2013/def/crashdump-head/sbin/savecore/dumpfile.c
  soc2013/def/crashdump-head/sbin/savecore/dumpfile.h
Modified:
  soc2013/def/crashdump-head/etc/defaults/rc.conf
  soc2013/def/crashdump-head/etc/rc.d/Makefile
  soc2013/def/crashdump-head/sbin/Makefile
  soc2013/def/crashdump-head/sbin/savecore/Makefile
  soc2013/def/crashdump-head/sbin/savecore/savecore.c
  soc2013/def/crashdump-head/sys/amd64/conf/GENERIC
  soc2013/def/crashdump-head/sys/conf/options
  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/kerneldump.h

Modified: soc2013/def/crashdump-head/etc/defaults/rc.conf
==============================================================================
--- soc2013/def/crashdump-head/etc/defaults/rc.conf	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/etc/defaults/rc.conf	Wed Apr 29 09:34:58 2015	(r284780)
@@ -581,6 +581,8 @@
 cron_program="/usr/sbin/cron"	# Which cron executable to run (if enabled).
 cron_dst="YES"		# Handle DST transitions intelligently (YES/NO)
 cron_flags=""		# Which options to pass to the cron daemon.
+cryptcore_enable="NO"	# Enable encrypted kernel crash dumps.
+cryptcore_pubkey=""	# Path to a public key.
 lpd_enable="NO"		# Run the line printer daemon.
 lpd_program="/usr/sbin/lpd"	# path to lpd, if you want a different one.
 lpd_flags=""		# Flags to lpd (if enabled).
@@ -589,8 +591,6 @@
 chkprintcap_flags="-d"	# Create missing directories by default.
 dumpdev="AUTO"		# Device to crashdump to (device name, AUTO, or NO).
 dumpdir="/var/crash"	# Directory where crash dumps are to be stored
-dumpkey_enable="YES"	# Run dumpkey to generate a symmetric key.
-dumpkey_pubkey="/var/crash/.public.key"	# Public key to encrypt a symmetric key.
 savecore_flags="-m 10"	# Used if dumpdev is enabled above, and present.
 			# By default, only the 10 most recent kernel dumps
 			# are saved.

Modified: soc2013/def/crashdump-head/etc/rc.d/Makefile
==============================================================================
--- soc2013/def/crashdump-head/etc/rc.d/Makefile	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/etc/rc.d/Makefile	Wed Apr 29 09:34:58 2015	(r284780)
@@ -25,6 +25,7 @@
 	cleanvar \
 	cleartmp \
 	cron \
+	cryptcore \
 	ctld \
 	ddb \
 	defaultroute \
@@ -32,7 +33,6 @@
 	devfs \
 	dhclient \
 	dmesg \
-	dumpkey \
 	dumpon \
 	fsck \
 	gbde \

Modified: soc2013/def/crashdump-head/sbin/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/Makefile	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sbin/Makefile	Wed Apr 29 09:34:58 2015	(r284780)
@@ -11,6 +11,7 @@
 	clri \
 	comcontrol \
 	conscontrol \
+	cryptcore \
 	ddb \
 	devfs \
 	dhclient \

Added: soc2013/def/crashdump-head/sbin/cryptcore/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/def/crashdump-head/sbin/cryptcore/Makefile	Wed Apr 29 09:34:58 2015	(r284780)
@@ -0,0 +1,12 @@
+PROG=	cryptcore
+
+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/cryptcore/cryptcore.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/def/crashdump-head/sbin/cryptcore/cryptcore.c	Wed Apr 29 09:34:58 2015	(r284780)
@@ -0,0 +1,311 @@
+#include <sys/types.h>
+#include <sys/kerneldump.h>
+#include <sys/sysctl.h>
+
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <pjdlog.h>
+
+#define	CRYPTCORE_DEVRANDOM	"/dev/random"
+
+#define	CRYPTCORE_CMD_GENKEY	0x01
+#define	CRYPTCORE_CMD_DECRYPT	0x02
+
+static void
+usage(void)
+{
+
+	pjdlog_exitx(1, "%s\n%s",
+	    "usage: cryptcore genkey [-Fv] -p publickey",
+	    "       cryptcore decrypt [-Fv] -p privatekey -k encryptedkey -i encryptedcore -o decryptedcore");
+}
+
+static void
+cryptcore_genkey(const char *pubkeyfile)
+{
+	uint8_t buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE];
+	uint8_t ciphertext[KERNELDUMP_CIPHERTEXT_SIZE];
+	FILE *fp;
+	RSA *pubkey;
+	int err, fd, pubkeysize, size;
+
+	PJDLOG_ASSERT(pubkeyfile != NULL);
+
+	pubkey = RSA_new();
+	if (pubkey == NULL)
+		pjdlog_exit(1, "Unable to allocate an RSA structure");
+
+	fd = open(CRYPTCORE_DEVRANDOM, O_RDONLY);
+	if (fd == -1)
+		pjdlog_exit(1, "Unable to open %s", CRYPTCORE_DEVRANDOM);
+	size = (int)read(fd, buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE);
+	err = errno;
+	close(fd);
+	if (size != KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE) {
+		errno = err;
+		pjdlog_exit(1, "Unable to read data from %s",
+		    CRYPTCORE_DEVRANDOM);
+	}
+
+	fp = fopen(pubkeyfile, "r");
+	if (fp == NULL)
+		pjdlog_exit(1, "Unable to open %s", pubkeyfile);
+	pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL);
+	err = errno;
+	fclose(fp);
+	if (pubkey == NULL) {
+		errno = err;
+		pjdlog_exit(1, "Unable to read data from %s", pubkeyfile);
+	}
+	pubkeysize = RSA_size(pubkey);
+	if (RSA_size(pubkey) > 8 * KERNELDUMP_CIPHERTEXT_SIZE) {
+		pjdlog_exitx(1, "The maximum RSA modulus size is %db.",
+		    8 * KERNELDUMP_CIPHERTEXT_SIZE);
+	}
+
+	if (RSA_public_encrypt(KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE, buf,
+	    ciphertext, pubkey, RSA_PKCS1_PADDING) != pubkeysize) {
+		pjdlog_exit(1, "Unable to encrypt an one-time key");
+	}
+
+	/*
+	 * From this moment keys have to be erased before exit.
+	 */
+	if (sysctlbyname("kern.ekcd.keymaterial", NULL, NULL, buf,
+	    KERNELDUMP_KEY_SIZE) != 0) {
+		pjdlog_errno(LOG_ERR, "Unable to set key material");
+		goto failed;
+	}
+	if (sysctlbyname("kern.ekcd.iv", NULL, NULL, buf + KERNELDUMP_KEY_SIZE,
+	    KERNELDUMP_IV_SIZE) != 0) {
+		pjdlog_errno(LOG_ERR, "Unable to set IV");
+		goto failed;
+	}
+	if (sysctlbyname("kern.ekcd.ciphertext", NULL, NULL, ciphertext,
+	    pubkeysize) != 0) {
+		pjdlog_errno(LOG_ERR, "Unable to set ciphertext");
+		goto failed;
+	}
+
+	bzero(buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE);
+	RSA_free(pubkey);
+
+	return;
+failed:
+	bzero(buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE);
+	RSA_free(pubkey);
+	exit(1);
+}
+
+static void
+cryptcore_decrypt(const char *privkeyfile, const char *keyfile,
+    const char *input, const char *output)
+{
+	uint8_t buf[KERNELDUMP_BUFFER_SIZE];
+	uint8_t ciphertext[KERNELDUMP_CIPHERTEXT_SIZE];
+	EVP_CIPHER_CTX ctx;
+	FILE *fp;
+	RSA *privkey;
+	int err, fd, ofd, privkeysize, size;
+	size_t bufused, bytes;
+
+	PJDLOG_ASSERT(privkeyfile != NULL);
+	PJDLOG_ASSERT(keyfile != NULL);
+	PJDLOG_ASSERT(input != NULL);
+	PJDLOG_ASSERT(output != NULL);
+
+	privkey = RSA_new();
+	if (privkey == NULL)
+		pjdlog_exit(1, "Unable to allocate an RSA structure");
+	EVP_CIPHER_CTX_init(&ctx);
+
+	fd = open(keyfile, O_RDONLY);
+	if (fd == -1)
+		pjdlog_exit(1, "Unable to open %s", keyfile);
+	size = (int)read(fd, ciphertext, KERNELDUMP_CIPHERTEXT_SIZE);
+	err = errno;
+	close(fd);
+	if (size != KERNELDUMP_CIPHERTEXT_SIZE) {
+		errno = err;
+		pjdlog_exit(1, "Unable to read data from %s", keyfile);
+	}
+
+	fp = fopen(privkeyfile, "r");
+	if (fp == NULL)
+		pjdlog_exit(1, "Unable to open %s", privkeyfile);
+	privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL);
+	err = errno;
+	fclose(fp);
+	if (privkey == NULL) {
+		errno = err;
+		pjdlog_exit(1, "Unable to read data from %s", privkeyfile);
+	}
+	/*
+	 * From this moment keys have to be erased before exit.
+	 */
+	privkeysize = RSA_size(privkey);
+	if (RSA_size(privkey) > 8 * KERNELDUMP_CIPHERTEXT_SIZE) {
+		pjdlog_error("The maximum RSA modulus size is %db.",
+		    8 * KERNELDUMP_CIPHERTEXT_SIZE);
+		goto failed;
+	}
+
+	if (RSA_private_decrypt(KERNELDUMP_CIPHERTEXT_SIZE, ciphertext, buf,
+	    privkey, RSA_PKCS1_PADDING) !=
+	    KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE) {
+		pjdlog_errno(LOG_ERR, "Unable to decrypt key and IV");
+		goto failed;
+	}
+
+	fd = open(input, O_RDONLY);
+	if (fd == -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;
+	}
+
+	EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, buf,
+	    buf + KERNELDUMP_KEY_SIZE);
+	EVP_CIPHER_CTX_set_key_length(&ctx, KERNELDUMP_KEY_SIZE);
+	EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+	bufused = 0;
+	while ((bytes = read(fd, buf + bufused,
+	    KERNELDUMP_BUFFER_SIZE - bufused)) > 0) {
+		bufused += bytes;
+		if (bufused != KERNELDUMP_BUFFER_SIZE)
+			continue;
+
+		if (EVP_DecryptUpdate(&ctx, buf, &size, buf,
+		    KERNELDUMP_BUFFER_SIZE) == 0) {
+			pjdlog_errno(LOG_ERR, "Unable to decrypt core.");
+			goto failed;
+		}
+		PJDLOG_ASSERT(size == KERNELDUMP_BUFFER_SIZE);
+
+		if (write(ofd, buf, KERNELDUMP_BUFFER_SIZE) !=
+		    KERNELDUMP_BUFFER_SIZE) {
+			pjdlog_errno(LOG_ERR, "Unable to write data to %s",
+			    output);
+			goto failed;
+		}
+		bufused = 0;
+	}
+
+	bzero(buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE);
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	RSA_free(privkey);
+
+	close(ofd);
+	close(fd);
+
+	return;
+failed:
+	bzero(buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE);
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	RSA_free(privkey);
+	exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+	const char *input, *keyfile, *optstr, *output, *rsakeyfile;
+	int cmd, debug;
+	char ch;
+	bool foreground;
+
+	pjdlog_init(PJDLOG_MODE_STD);
+	pjdlog_prefix_set("(cryptcore) ");
+
+	if (argc < 2)
+		usage();
+
+	optstr = NULL;
+	if (strcmp("genkey", argv[1]) == 0) {
+		cmd = CRYPTCORE_CMD_GENKEY;
+		optstr = "Fp:v";
+	} else if (strcmp("decrypt", argv[1]) == 0) {
+		cmd = CRYPTCORE_CMD_DECRYPT;
+		optstr = "Fi:k:o:p:v";
+	} else {
+		usage();
+	}
+	argc--;
+	argv++;
+
+	foreground = false;
+	debug = 0;
+	rsakeyfile = NULL;
+	while ((ch = getopt(argc, argv, optstr)) != -1) {
+		switch (ch) {
+		case 'F':
+			foreground = 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();
+
+	switch (cmd) {
+	case CRYPTCORE_CMD_GENKEY:
+		if (rsakeyfile == NULL)
+			usage();
+		break;
+	case CRYPTCORE_CMD_DECRYPT:
+		if (input == NULL || keyfile == NULL || output == NULL ||
+		    rsakeyfile == NULL) {
+			usage();
+		}
+		break;
+	}
+
+	if (!foreground)
+		pjdlog_mode_set(PJDLOG_MODE_SYSLOG);
+	pjdlog_debug_set(debug);
+
+	switch (cmd) {
+	case CRYPTCORE_CMD_GENKEY:
+		cryptcore_genkey(rsakeyfile);
+		break;
+	case CRYPTCORE_CMD_DECRYPT:
+		cryptcore_decrypt(rsakeyfile, keyfile, input, output);
+		break;
+	}
+
+	pjdlog_fini();
+
+	return (0);
+}

Modified: soc2013/def/crashdump-head/sbin/savecore/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/Makefile	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sbin/savecore/Makefile	Wed Apr 29 09:34:58 2015	(r284780)
@@ -1,10 +1,9 @@
 # $FreeBSD$
 
-SYS=	${.CURDIR}/../../sys
-
 PROG=	savecore
 LIBADD=	z xo
-CFLAGS+=-I${SYS}
 MAN=	savecore.8
 
+CFLAGS+=-I${.CURDIR}/../../sys
+
 .include <bsd.prog.mk>

Modified: soc2013/def/crashdump-head/sbin/savecore/savecore.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/savecore.c	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sbin/savecore/savecore.c	Wed Apr 29 09:34:58 2015	(r284780)
@@ -82,8 +82,6 @@
 #include <unistd.h>
 #include <libxo/xo.h>
 
-#include "dumpfile.h"
-
 /* The size of the buffer used for I/O. */
 #define	BUFFERSIZE	(1024*1024)
 
@@ -185,6 +183,24 @@
 	fclose(fp);
 }
 
+static void
+writekey(const char *keyname, struct kerneldumpheader *kdh)
+{
+	int fd;
+
+	fd = open(keyname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	if (fd == -1) {
+		syslog(LOG_ERR, "Unable to open %s to write a key.", keyname);
+		exit(1);
+	}
+	if (write(fd, kdh->ciphertext, KERNELDUMP_CIPHERTEXT_SIZE) !=
+	    KERNELDUMP_CIPHERTEXT_SIZE) {
+		syslog(LOG_ERR, "Unable to write a key to %s.", keyname);
+		exit(1);
+	}
+	close(fd);
+}
+
 static off_t
 file_size(const char *path)
 {
@@ -317,9 +333,7 @@
 			nerr++;
 			return (-1);
 		}
-		if (compress) {
-			nw = fwrite(buf, 1, wl, fp);
-		} else if (encrypted) {
+		if (compress || encrypted) {
 			nw = fwrite(buf, 1, wl, fp);
 		} else {
 			for (nw = 0; nw < nr; nw = he) {
@@ -495,7 +509,7 @@
 		printf("sectorsize = %u\n", sectorsize);
 	}
 
-	lasthd = mediasize - 2 * sectorsize;
+	lasthd = mediasize - sizeof(kdhl);
 	lseek(fd, lasthd, SEEK_SET);
 	error = read(fd, &kdhl, sizeof kdhl);
 	if (error != sizeof kdhl) {
@@ -640,15 +654,14 @@
 	}
 
 	oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/
+	if (encrypted) {
+		snprintf(keyname, sizeof(keyname), "key.%d", bounds);
+		writekey(keyname, &kdhl);
+	}
 	if (compress) {
 		snprintf(corename, sizeof(corename), "%s.%d.gz",
 		    istextdump ? "textdump.tar" : "vmcore", bounds);
 		fp = zopen(corename, "w");
-	} else if (encrypted) {
-		snprintf(corename, sizeof(corename), "%s.%d",
-		    istextdump ? "textdump.tar" : "vmcore", bounds);
-		snprintf(keyname, sizeof(keyname), "key.%d", bounds);
-		fp = dopen(corename, "w", keyname, &kdhl);
 	} else {
 		snprintf(corename, sizeof(corename), "%s.%d",
 		    istextdump ? "textdump.tar" : "vmcore", bounds);
@@ -688,8 +701,8 @@
 	xo_finish_h(xoinfo);
 	fclose(info);
 
-	syslog(LOG_NOTICE, "writing %score to %s/%s",
-	    compress ? "compressed " : (encrypted ? "encrypted " : ""),
+	syslog(LOG_NOTICE, "writing %s%score to %s/%s",
+	    encrypted ? "encrypted " : "", compress ? "compressed " : "",
 	    savedir, corename);
 
 	if (istextdump) {
@@ -782,7 +795,7 @@
 	if (argc < 0)
 		exit(1);
 
-	while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1)
+	while ((ch = getopt(argc, argv, "Ccefkm:vz")) != -1)
 		switch(ch) {
 		case 'C':
 			checkfor = 1;
@@ -818,9 +831,7 @@
 		}
 	if (checkfor && (clear || force || keep))
 		usage();
-	if (clear && (compress || encrypted || keep))
-		usage();
-	if (compress && encrypted)
+	if (clear && (compress || keep))
 		usage();
 	if (maxdumps > 0 && (checkfor || clear))
 		usage();

Modified: soc2013/def/crashdump-head/sys/amd64/conf/GENERIC
==============================================================================
--- soc2013/def/crashdump-head/sys/amd64/conf/GENERIC	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sys/amd64/conf/GENERIC	Wed Apr 29 09:34:58 2015	(r284780)
@@ -355,4 +355,4 @@
 device		netmap			# netmap(4) support
 
 # Unattended encrypted kernel crash dumps 	 
-options		ENCRYPT_CRASH_DUMP
+options		EKCD

Modified: soc2013/def/crashdump-head/sys/conf/options
==============================================================================
--- soc2013/def/crashdump-head/sys/conf/options	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sys/conf/options	Wed Apr 29 09:34:58 2015	(r284780)
@@ -938,4 +938,4 @@
 RANDOM_DEBUG	opt_random.h
 
 # Unattended encrypted kernel crash dumps
-ENCRYPT_CRASH_DUMP	opt_ecd.h
+EKCD		opt_ekcd.h

Modified: soc2013/def/crashdump-head/sys/kern/kern_dump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_dump.c	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sys/kern/kern_dump.c	Wed Apr 29 09:34:58 2015	(r284780)
@@ -47,7 +47,7 @@
 #include <machine/md_var.h>
 #include <machine/pcb.h>
 
-CTASSERT(sizeof(struct kerneldumpheader) == 512);
+CTASSERT((sizeof(struct kerneldumpheader) % 512) == 0);
 
 /*
  * Don't touch the first SIZEOF_METADATA bytes on the dump device. This

Modified: soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Wed Apr 29 09:34:58 2015	(r284780)
@@ -38,7 +38,7 @@
 __FBSDID("$FreeBSD$");
 
 #include "opt_ddb.h"
-#include "opt_ecd.h"
+#include "opt_ekcd.h"
 #include "opt_kdb.h"
 #include "opt_panic.h"
 #include "opt_sched.h"
@@ -137,12 +137,30 @@
 SYSCTL_INT(_kern_shutdown, OID_AUTO, show_busybufs, CTLFLAG_RW,
 	&show_busybufs, 0, "");
 
-#ifdef ENCRYPT_CRASH_DUMP
+#ifdef EKCD
 static struct kerneldumpkey dumperkey;
 static struct kerneldumpbuffer dumperbuffer;
-SYSCTL_STRUCT(_kern, OID_AUTO, dumpkey, CTLFLAG_RW, &dumperkey,
-    kerneldumpkey, "Kernel crash dump key");
-#endif
+
+static int kerneldump_sysctl_keymaterial(SYSCTL_HANDLER_ARGS);
+static int kerneldump_sysctl_iv(SYSCTL_HANDLER_ARGS);
+
+SYSCTL_NODE(_kern, OID_AUTO, ekcd, CTLFLAG_RW, 0,
+    "Encrypted kernel crash dumps");
+
+SYSCTL_INT(_kern_ekcd, OID_AUTO, enable, CTLFLAG_RW, &dumperkey.kdk_enable,
+    0, "Enable encrypted kernel crash dumps");
+
+SYSCTL_PROC(_kern_ekcd, OID_AUTO, keymaterial, CTLTYPE_OPAQUE | CTLFLAG_WR,
+    NULL, 0, kerneldump_sysctl_keymaterial, "",
+    "Key material used to encrypt a crash dump");
+
+SYSCTL_PROC(_kern_ekcd, OID_AUTO, iv, CTLTYPE_OPAQUE | CTLFLAG_WR, NULL, 0,
+    kerneldump_sysctl_iv, "", "IV used to encrypt a crash dump");
+
+SYSCTL_OPAQUE(_kern_ekcd, OID_AUTO, ciphertext, CTLFLAG_WR,
+    &dumperkey.kdk_ciphertext, KERNELDUMP_CIPHERTEXT_SIZE, "",
+    "Encrypted key material and IV");
+#endif /* EKCD */
 
 /*
  * Variable panicstr contains argument to first call to panic; used as flag
@@ -829,6 +847,61 @@
 		printf("done\n");
 }
 
+#ifdef EKCD
+static int
+kerneldump_sysctl_keymaterial(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+
+	error = sysctl_handle_opaque(oidp, &dumperkey.kdk_keymaterial,
+	    KERNELDUMP_KEY_SIZE, req);
+	if (error != 0)
+		return (error);
+
+	if (req->newptr != NULL) {
+		rijndael_makeKey(&dumperkey.kdk_ki, DIR_ENCRYPT,
+		    8 * KERNELDUMP_KEY_SIZE, dumperkey.kdk_keymaterial);
+	}
+
+	return (0);
+}
+
+static int
+kerneldump_sysctl_iv(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+
+	error = sysctl_handle_opaque(oidp, &dumperkey.kdk_iv,
+	    KERNELDUMP_IV_SIZE, req);
+	if (error != 0)
+		return (error);
+
+	if (req->newptr != NULL) {
+		rijndael_cipherInit(&dumperkey.kdk_ci, MODE_CBC,
+		    dumperkey.kdk_iv);
+	}
+
+	return (0);
+}
+
+static void
+kerneldump_crypto_init(struct dumperinfo *di, struct kerneldumpkey *kdk,
+    struct kerneldumpbuffer *kdb)
+{
+
+	if (kdk == NULL || kdb == NULL) {
+		printf("Attempt to use an invalid kernel dump key or buffer.");
+		return;
+	}
+
+	bzero(kdk, sizeof(struct kerneldumpkey));
+	bzero(kdb, sizeof(struct kerneldumpbuffer));
+
+	di->kdk = kdk;
+	di->kdb = kdb;
+}
+#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");
@@ -852,7 +925,8 @@
 	if (dumper.dumper != NULL)
 		return (EBUSY);
 	dumper = *di;
-#ifdef ENCRYPT_CRASH_DUMP
+
+#ifdef EKCD
 	kerneldump_crypto_init(&dumper, &dumperkey, &dumperbuffer);
 #endif
 
@@ -864,8 +938,8 @@
 	return (0);
 }
 
-/* Call dumper with encrypted data. */
-int
+/* Encrypt data and call dumper. */
+static int
 dump_encrypted_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
     off_t offset, size_t length)
 {
@@ -877,47 +951,47 @@
 	kdk = di->kdk;
 	kdb = di->kdb;
 
-	/* Data have to be written one after another. */
-	if (kdb->offset != 0 && kdb->offset != offset &&
-	    kdb->offset + kdb->used != offset) {
+	/* Data have to be written continuously. */
+	if (kdb->kdb_offset != 0 && kdb->kdb_offset != offset &&
+	    kdb->kdb_offset + kdb->kdb_used != offset) {
 		return (EINVAL);
 	}
 
 	/* Write kernel dump headers. */
-	if (kdb->offset == 0 || kdb->offset == di->mediaoffset +
+	if (kdb->kdb_offset == 0 || kdb->kdb_offset == di->mediaoffset +
 	    di->mediasize - sizeof(struct kerneldumpheader)) {
-		kdb->offset = offset + length;
+		kdb->kdb_offset = offset + length;
 		return (di->dumper(di->priv, virtual, physical, offset,
 		    length));
 	}
 
-	while (kdb->used + length >= KERNELDUMP_BUFFER_SIZE) {
-		len = KERNELDUMP_BUFFER_SIZE - kdb->used;
-		memcpy(kdb->buf + kdb->used, virtual, len);
-		kdb->used += len;
+	while (kdb->kdb_used + length >= KERNELDUMP_BUFFER_SIZE) {
+		len = KERNELDUMP_BUFFER_SIZE - kdb->kdb_used;
+		memcpy(kdb->kdb_buf + kdb->kdb_used, virtual, len);
+		kdb->kdb_used += len;
 
-		error = rijndael_blockEncrypt(&kdk->ci, &kdk->ki, kdb->buf,
-		    KERNELDUMP_BUFFER_SIZE * 8, kdb->buf);
+		error = rijndael_blockEncrypt(&kdk->kdk_ci, &kdk->kdk_ki,
+		    kdb->kdb_buf, 8 * KERNELDUMP_BUFFER_SIZE, kdb->kdb_buf);
 		if (error <= 0)
 			return (EIO);
-		error = rijndael_cipherInit(&kdk->ci, MODE_CBC, kdb->buf +
-		    KERNELDUMP_BUFFER_SIZE - KERNELDUMP_IV_SIZE);
+		error = rijndael_cipherInit(&kdk->kdk_ci, MODE_CBC,
+		    kdb->kdb_buf + KERNELDUMP_BUFFER_SIZE - KERNELDUMP_IV_SIZE);
 		if (error <= 0)
 			return (EIO);
 
-		error = di->dumper(di->priv, kdb->buf, physical, kdb->offset,
-		    KERNELDUMP_BUFFER_SIZE);
-		if (error)
+		error = di->dumper(di->priv, kdb->kdb_buf, physical,
+		    kdb->kdb_offset, KERNELDUMP_BUFFER_SIZE);
+		if (error != 0)
 			return (error);
 
-		kdb->used = 0;
-		kdb->offset += KERNELDUMP_BUFFER_SIZE;
+		kdb->kdb_used = 0;
+		kdb->kdb_offset += KERNELDUMP_BUFFER_SIZE;
 		virtual = (void *)((char *)virtual + len);
 		length -= len;
 	}
 	if (length > 0) {
-		memcpy(kdb->buf + kdb->used, virtual, length);
-		kdb->used += length;
+		memcpy(kdb->kdb_buf + kdb->kdb_used, virtual, length);
+		kdb->kdb_used += length;
 	}
 
 	return (0);
@@ -937,26 +1011,13 @@
 		    (uintmax_t)length, (intmax_t)di->mediasize);
 		return (ENOSPC);
 	}
-#ifdef ENCRYPT_CRASH_DUMP
-	return (dump_encrypted_write(di, virtual, physical, offset, length));
-#else
-	return (di->dumper(di->priv, virtual, physical, offset, length));
-#endif
-}
-
-void
-kerneldump_crypto_init(struct dumperinfo *di, struct kerneldumpkey *kdk,
-    struct kerneldumpbuffer *kdb)
-{
-
-	if (kdk == NULL || kdb == NULL) {
-		printf("Attempt to initialize a kernel dump key and buffer.");
-		return;
+#ifdef EKCD
+	if (di->kdk->kdk_enable == 1) {
+		return (dump_encrypted_write(di, virtual, physical, offset,
+		    length));
 	}
-
-	di->kdk = kdk;
-	di->kdb = kdb;
-	bzero(di->kdb, sizeof(struct kerneldumpbuffer));
+#endif
+	return (di->dumper(di->priv, virtual, physical, offset, length));
 }
 
 void
@@ -976,7 +1037,9 @@
 	strncpy(kdh->versionstring, version, sizeof(kdh->versionstring));
 	if (panicstr != NULL)
 		strncpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
-	memcpy(kdh->ciphertext, dumper.kdk->ciphertext,
+#ifdef EKCD
+	memcpy(kdh->ciphertext, dumperkey.kdk_ciphertext,
 	    KERNELDUMP_CIPHERTEXT_SIZE);
+#endif
 	kdh->parity = kerneldump_parity(kdh);
 }

Modified: soc2013/def/crashdump-head/sys/sys/conf.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/conf.h	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sys/sys/conf.h	Wed Apr 29 09:34:58 2015	(r284780)
@@ -308,7 +308,9 @@
 int dev_stdclone(char *_name, char **_namep, const char *_stem, int *_unit);
 EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn);
 
-/* Stuff relating to kernel-dump */
+/* EKCD structures. */
+struct kerneldumpkey;
+struct kerneldumpbuffer;
 
 struct dumperinfo {
 	dumper_t *dumper;	/* Dumping function. */
@@ -317,6 +319,8 @@
 	u_int	maxiosize;	/* Max size allowed for an individual I/O */
 	off_t   mediaoffset;	/* Initial offset in bytes. */
 	off_t   mediasize;	/* Space available in bytes. */
+	struct kerneldumpkey *kdk; /* Kernel dump key. */
+	struct kerneldumpbuffer *kdb; /* Kernel dump buffer. */
 };
 
 int set_dumper(struct dumperinfo *, const char *_devname, struct thread *td);

Modified: soc2013/def/crashdump-head/sys/sys/kerneldump.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/kerneldump.h	Wed Apr 29 08:56:56 2015	(r284779)
+++ soc2013/def/crashdump-head/sys/sys/kerneldump.h	Wed Apr 29 09:34:58 2015	(r284780)
@@ -53,6 +53,11 @@
 #define	htod64(x)	(x)
 #endif
 
+#define	KERNELDUMP_BUFFER_SIZE		1024
+#define	KERNELDUMP_CIPHERTEXT_SIZE	512
+#define	KERNELDUMP_IV_SIZE		16
+#define	KERNELDUMP_KEY_SIZE		32
+
 /*
  * All uintX_t fields are in dump byte order, which is the same as
  * network byte order. Use the macros defined above to read or
@@ -75,10 +80,6 @@
 #define	KERNELDUMP_POWERPC_VERSION	1
 #define	KERNELDUMP_SPARC64_VERSION	1
 #define	KERNELDUMP_TEXT_VERSION		1
-#define	KERNELDUMP_KEY_SIZE		32
-#define	KERNELDUMP_IV_SIZE		16
-#define	KERNELDUMP_CIPHERTEXT_SIZE	512
-#define	KERNELDUMP_BUFFER_SIZE		512
 	uint64_t	dumplength;		/* excl headers */
 	uint64_t	dumptime;
 	uint32_t	blocksize;
@@ -89,12 +90,6 @@
 	uint32_t	parity;
 };
 
-struct kerneldumpkey {
-	char		ciphertext[KERNELDUMP_CIPHERTEXT_SIZE];
-	keyInstance	ki;
-	cipherInstance	ci;
-};
-
 /*
  * Parity calculation is endian insensitive.
  */
@@ -112,6 +107,21 @@
 }
 
 #ifdef _KERNEL
+struct kerneldumpkey {
+	int		kdk_enable;
+	uint8_t		kdk_keymaterial[KERNELDUMP_KEY_SIZE];
+	uint8_t		kdk_iv[KERNELDUMP_IV_SIZE];
+	uint8_t		kdk_ciphertext[KERNELDUMP_CIPHERTEXT_SIZE];
+	keyInstance	kdk_ki;
+	cipherInstance	kdk_ci;
+};
+
+struct kerneldumpbuffer {
+	uint8_t	kdb_buf[KERNELDUMP_BUFFER_SIZE];
+	size_t	kdb_used;
+	off_t	kdb_offset;
+};
+
 struct dump_pa {
 	vm_paddr_t pa_start;
 	vm_paddr_t pa_size;


More information about the svn-soc-all mailing list