Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Jun 2015 11:50:00 GMT
From:      def@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r286773 - in soc2013/def/crashdump-head: sbin/cryptcore sbin/savecore sys/amd64/amd64 sys/ddb sys/kern sys/sys
Message-ID:  <201506071150.t57Bo0CT042516@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: def
Date: Sun Jun  7 11:49:59 2015
New Revision: 286773
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=286773

Log:
  Dump an encrypted key of arbitrary size separately from a header.

Modified:
  soc2013/def/crashdump-head/sbin/cryptcore/cryptcore.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/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/sbin/cryptcore/cryptcore.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/cryptcore/cryptcore.c	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sbin/cryptcore/cryptcore.c	Sun Jun  7 11:49:59 2015	(r286773)
@@ -30,8 +30,8 @@
 static void
 cryptcore_genkey(const char *pubkeyfile)
 {
-	uint8_t buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE];
-	uint8_t ciphertext[KERNELDUMP_CIPHERTEXT_SIZE];
+	uint8_t key[KERNELDUMP_KEY_SIZE];
+	uint8_t *encryptedkey;
 	FILE *fp;
 	RSA *pubkey;
 	int pubkeysize;
@@ -49,43 +49,41 @@
 	fclose(fp);
 	if (pubkey == NULL)
 		pjdlog_exitx(1, "Unable to read data from %s.", pubkeyfile);
+
 	pubkeysize = RSA_size(pubkey);
-	if (pubkeysize > (int)sizeof(ciphertext)) {
-		pjdlog_exitx(1, "The maximum RSA modulus size is %lub.",
-		    8 * sizeof(ciphertext));
-	}
+	encryptedkey = (uint8_t *)calloc(1, pubkeysize);
+	if (encryptedkey == NULL)
+		pjdlog_exitx(1, "Unable to allocate encrypted key");
 
-	arc4random_buf(buf, sizeof(buf));
-	if (RSA_public_encrypt(sizeof(buf), buf, ciphertext, pubkey,
+	arc4random_buf(key, sizeof(key));
+	if (RSA_public_encrypt(sizeof(key), key, encryptedkey, pubkey,
 	    RSA_PKCS1_PADDING) != pubkeysize) {
-		pjdlog_exitx(1, "Unable to encrypt the one-time key.");
+		pjdlog_errno(LOG_ERR, "Unable to encrypt the one-time key");
+		goto failed;
 	}
 
 	/*
 	 * From this moment on keys have to be erased before exit.
 	 */
-	if (sysctlbyname("security.ekcd.keymaterial", NULL, NULL, buf,
+	if (sysctlbyname("security.ekcd.keymaterial", NULL, NULL, key,
 	    KERNELDUMP_KEY_SIZE) != 0) {
 		pjdlog_errno(LOG_ERR, "Unable to set key material");
 		goto failed;
 	}
-	if (sysctlbyname("security.ekcd.iv", NULL, NULL,
-	    buf + KERNELDUMP_KEY_SIZE, KERNELDUMP_IV_SIZE) != 0) {
-		pjdlog_errno(LOG_ERR, "Unable to set IV");
-		goto failed;
-	}
-	if (sysctlbyname("security.ekcd.ciphertext", NULL, NULL, ciphertext,
-	    pubkeysize) != 0) {
-		pjdlog_errno(LOG_ERR, "Unable to set ciphertext");
+	if (sysctlbyname("security.ekcd.encryptedkey", NULL, NULL,
+	    encryptedkey, pubkeysize) != 0) {
+		pjdlog_errno(LOG_ERR, "Unable to set encrypted key");
 		goto failed;
 	}
 
-	bzero(buf, sizeof(buf));
+	bzero(key, sizeof(key));
+	free(encryptedkey);
 	RSA_free(pubkey);
 
 	return;
 failed:
-	bzero(buf, sizeof(buf));
+	bzero(key, sizeof(key));
+	free(encryptedkey);
 	RSA_free(pubkey);
 	exit(1);
 }
@@ -94,10 +92,10 @@
 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];
+	uint8_t buf[KERNELDUMP_BUFFER_SIZE], key[KERNELDUMP_KEY_SIZE];
 	EVP_CIPHER_CTX ctx;
 	FILE *fp;
+	struct kerneldumpkey *kdk;
 	RSA *privkey;
 	int err, fd, ofd, privkeysize, size;
 	size_t bufused, bytes;
@@ -109,19 +107,29 @@
 
 	ofd = -1;
 	fd = -1;
+
 	privkey = RSA_new();
 	if (privkey == NULL)
 		pjdlog_exitx(1, "Unable to allocate an RSA structure.");
 	EVP_CIPHER_CTX_init(&ctx);
 
+	kdk = (struct kerneldumpkey *)calloc(1, sizeof(struct kerneldumpkey));
+	if (kdk == NULL)
+		pjdlog_exit(1, "Unable to allocate kernel dump key");
+
 	fd = open(keyfile, O_RDONLY);
 	if (fd == -1)
 		pjdlog_exit(1, "Unable to open %s", keyfile);
-	size = (int)read(fd, ciphertext, sizeof(ciphertext));
+	size = (int)read(fd, kdk, sizeof(struct kerneldumpkey));
+	if (size == sizeof(struct kerneldumpkey)) {
+		kdk = (struct kerneldumpkey *)realloc(kdk, kdk->kdk_size);
+		size += read(fd, &kdk->kdk_encryptedkey,
+		    kdk->kdk_size - sizeof(struct kerneldumpkey));
+	}
 	err = errno;
 	close(fd);
 	fd = -1;
-	if (size != sizeof(ciphertext)) {
+	if (size != (int)kdk->kdk_size) {
 		errno = err;
 		pjdlog_exit(1, "Unable to read data from %s", keyfile);
 	}
@@ -133,19 +141,19 @@
 	fclose(fp);
 	if (privkey == NULL)
 		pjdlog_exitx(1, "Unable to read data from %s.", privkeyfile);
+
 	/*
 	 * From this moment on keys have to be erased before exit.
 	 */
 	privkeysize = RSA_size(privkey);
-	if (privkeysize > (int)sizeof(ciphertext)) {
-		pjdlog_error("The maximum RSA modulus size is %lub.",
-		    8 * sizeof(ciphertext));
+	if (privkeysize != kdk->kdk_encryptedkeylen) {
+		pjdlog_error("RSA modulus size mismatch: equals %db and should be %db.",
+		    8 * privkeysize, 8 * kdk->kdk_encryptedkeylen);
 		goto failed;
 	}
-
-	if (RSA_private_decrypt(sizeof(ciphertext), ciphertext, buf, privkey,
-	    RSA_PKCS1_PADDING) != KERNELDUMP_KEY_SIZE + KERNELDUMP_IV_SIZE) {
-		pjdlog_error("Unable to decrypt key and IV.");
+	if (RSA_private_decrypt(kdk->kdk_encryptedkeylen, kdk->kdk_encryptedkey,
+	    key, privkey, RSA_PKCS1_PADDING) != sizeof(key)) {
+		pjdlog_error("Unable to decrypt key.");
 		goto failed;
 	}
 
@@ -160,9 +168,8 @@
 		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_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;
@@ -186,6 +193,7 @@
 		bufused = 0;
 	}
 
+	bzero(key, sizeof(key));
 	bzero(buf, sizeof(buf));
 	EVP_CIPHER_CTX_cleanup(&ctx);
 	RSA_free(privkey);
@@ -199,6 +207,7 @@
 		close(ofd);
 	if (fd >= 0)
 		close(fd);
+	bzero(key, sizeof(key));
 	bzero(buf, sizeof(buf));
 	EVP_CIPHER_CTX_cleanup(&ctx);
 	RSA_free(privkey);

Modified: soc2013/def/crashdump-head/sbin/savecore/savecore.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/savecore.c	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sbin/savecore/savecore.c	Sun Jun  7 11:49:59 2015	(r286773)
@@ -74,6 +74,7 @@
 #include <paths.h>
 #include <signal.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -183,22 +184,26 @@
 	fclose(fp);
 }
 
-static void
-writekey(const char *keyname, struct kerneldumpheader *kdh)
+static bool
+writekey(const char *keyname, struct kerneldumpkey *kdk)
 {
 	int fd;
 
 	fd = open(keyname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 	if (fd == -1) {
 		syslog(LOG_ERR, "Unable to open %s to write the key.", keyname);
-		exit(1);
+		return (false);
 	}
-	if (write(fd, kdh->ciphertext, KERNELDUMP_CIPHERTEXT_SIZE) !=
-	    KERNELDUMP_CIPHERTEXT_SIZE) {
+
+	if (write(fd, kdk, kerneldumpkey_size(kdk)) !=
+	    (ssize_t)kerneldumpkey_size(kdk)) {
 		syslog(LOG_ERR, "Unable to write the key to %s.", keyname);
-		exit(1);
+		close(fd);
+		return (false);
 	}
+
 	close(fd);
+	return (true);
 }
 
 static off_t
@@ -452,6 +457,7 @@
 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];
@@ -464,6 +470,7 @@
 	int bounds, status;
 	u_int sectorsize, xostyle;
 	int istextdump;
+	uint32_t dumpkeysize;
 
 	bounds = getbounds();
 	mediasize = 0;
@@ -587,7 +594,8 @@
 			goto closefd;
 	}
 	dumpsize = dtoh64(kdhl.dumplength);
-	firsthd = lasthd - dumpsize - sizeof kdhf;
+	dumpkeysize = dtoh32(kdhl.dumpkeysize);
+	firsthd = lasthd - dumpsize - sizeof kdhf - dumpkeysize;
 	lseek(fd, firsthd, SEEK_SET);
 	error = read(fd, &kdhf, sizeof kdhf);
 	if (error != sizeof kdhf) {
@@ -654,10 +662,6 @@
 	}
 
 	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);
@@ -701,6 +705,28 @@
 	xo_finish_h(xoinfo);
 	fclose(info);
 
+	if (encrypted) {
+		kdk = (struct kerneldumpkey *)calloc(1, dumpkeysize);
+		if (kdk == NULL) {
+			syslog(LOG_ERR, "Unable to allocate kernel dump key.");
+			nerr++;
+			goto closefd;
+		}
+
+		error = read(fd, kdk, dumpkeysize);
+		if (error != (int)dumpkeysize) {
+			syslog(LOG_ERR, "Unable to read kernel dump key.");
+			nerr++;
+			goto closefd;
+		}
+
+		snprintf(keyname, sizeof(keyname), "key.%d", bounds);
+		if (!writekey(keyname, kdk)) {
+			nerr++;
+			goto closefd;
+		}
+	}
+
 	syslog(LOG_NOTICE, "writing %s%score to %s/%s",
 	    encrypted ? "encrypted " : "", compress ? "compressed " : "",
 	    savedir, corename);

Modified: soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c
==============================================================================
--- soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sys/amd64/amd64/minidump_machdep.c	Sun Jun  7 11:49:59 2015	(r286773)
@@ -320,12 +320,14 @@
 	dumpsize += PAGE_SIZE;
 
 	/* Determine dump offset on device. */
-	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
+	if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2 +
+	    kerneldumpkey_size(di->kdk)) {
 		error = E2BIG;
 		goto fail;
 	}
 	dumplo = di->mediaoffset + di->mediasize - dumpsize;
 	dumplo -= sizeof(kdh) * 2;
+	dumplo -= kerneldumpkey_size(di->kdk);
 	progress = dumpsize;
 
 	/* Initialize mdhdr */
@@ -339,17 +341,24 @@
 	mdhdr.dmapbase = DMAP_MIN_ADDRESS;
 	mdhdr.dmapend = DMAP_MAX_ADDRESS;
 
-	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, dumpsize, di->blocksize);
+	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, dumpsize,
+	    kerneldumpkey_size(di->kdk), di->blocksize);
 
 	printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20,
 	    ptoa((uintmax_t)physmem) / 1048576);
 
 	/* Dump leader */
-	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+	error = dump_write_header(di, &kdh, 0, dumplo);
 	if (error)
 		goto fail;
 	dumplo += sizeof(kdh);
 
+	/* Dump key */
+	error = dump_write_key(di, di->kdk, 0, dumplo);
+	if (error)
+		goto fail;
+	dumplo += kerneldumpkey_size(di->kdk);
+
 	/* Dump my header */
 	bzero(&fakepd, sizeof(fakepd));
 	bcopy(&mdhdr, &fakepd, sizeof(mdhdr));
@@ -433,7 +442,7 @@
 		goto fail;
 
 	/* Dump trailer */
-	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
+	error = dump_write_header(di, &kdh, 0, dumplo);
 	if (error)
 		goto fail;
 	dumplo += sizeof(kdh);

Modified: soc2013/def/crashdump-head/sys/ddb/db_textdump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/ddb/db_textdump.c	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sys/ddb/db_textdump.c	Sun Jun  7 11:49:59 2015	(r286773)
@@ -456,7 +456,8 @@
 	 */
 	textdump_offset = di->mediasize - sizeof(kdh);
 	textdump_saveoff(&trailer_offset);
-	mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, 0, TEXTDUMP_BLOCKSIZE);
+	mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, 0,
+	    kerneldumpkey_size(di->kdk), TEXTDUMP_BLOCKSIZE);
 	(void)textdump_writenextblock(di, (char *)&kdh);
 
 	/*
@@ -482,7 +483,7 @@
 	 */
 	dumplen = trailer_offset - (textdump_offset + TEXTDUMP_BLOCKSIZE);
 	mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, dumplen,
-	    TEXTDUMP_BLOCKSIZE);
+	    kerneldumpkey_size(di->kdk), TEXTDUMP_BLOCKSIZE);
 	(void)textdump_writenextblock(di, (char *)&kdh);
 	textdump_restoreoff(trailer_offset);
 	(void)textdump_writenextblock(di, (char *)&kdh);

Modified: soc2013/def/crashdump-head/sys/kern/kern_dump.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_dump.c	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sys/kern/kern_dump.c	Sun Jun  7 11:49:59 2015	(r286773)
@@ -330,7 +330,7 @@
 	dumplo -= sizeof(kdh) * 2;
 
 	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize,
-	    di->blocksize);
+	    kerneldumpkey_size(di->kdk), di->blocksize);
 
 	printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20,
 	    ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS);

Modified: soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Sun Jun  7 11:49:59 2015	(r286773)
@@ -138,28 +138,35 @@
 	&show_busybufs, 0, "");
 
 #ifdef EKCD
-static struct kerneldumpkey dumperkey;
-static struct kerneldumpbuffer dumperbuffer;
+MALLOC_DEFINE(M_KDK, "kerneldumpkey", "Kernel dump key structure");
+
+static struct kerneldumpcrypto {
+	int		kdc_enable;
+	uint8_t		kdc_key[KERNELDUMP_KEY_SIZE];
+	uint8_t		kdc_iv[KERNELDUMP_IV_SIZE];
+	keyInstance	kdc_ki;
+	cipherInstance	kdc_ci;
+	off_t		kdc_offset;
+	uint8_t		kdc_buf[KERNELDUMP_BUFFER_SIZE];
+	size_t		kdc_bufused;
+} dumpcrypto;
+
+static struct kerneldumpkey *dumpkey;
 
 static int kerneldump_sysctl_keymaterial(SYSCTL_HANDLER_ARGS);
-static int kerneldump_sysctl_iv(SYSCTL_HANDLER_ARGS);
+static int kerneldump_sysctl_encryptedkey(SYSCTL_HANDLER_ARGS);
 
 SYSCTL_NODE(_security, OID_AUTO, ekcd, CTLFLAG_RW, 0,
     "Encrypted kernel crash dumps");
 
-SYSCTL_INT(_security_ekcd, OID_AUTO, enable, CTLFLAG_RW, &dumperkey.kdk_enable,
+SYSCTL_INT(_security_ekcd, OID_AUTO, enable, CTLFLAG_RW, &dumpcrypto.kdc_enable,
     0, "Enable encrypted kernel crash dumps");
 
 SYSCTL_PROC(_security_ekcd, OID_AUTO, keymaterial, CTLTYPE_OPAQUE | CTLFLAG_WR,
-    NULL, 0, kerneldump_sysctl_keymaterial, "",
-    "Key material used to encrypt a crash dump");
-
-SYSCTL_PROC(_security_ekcd, OID_AUTO, iv, CTLTYPE_OPAQUE | CTLFLAG_WR, NULL, 0,
-    kerneldump_sysctl_iv, "", "IV used to encrypt a crash dump");
+    NULL, 0, kerneldump_sysctl_keymaterial, "", "Key material");
 
-SYSCTL_OPAQUE(_security_ekcd, OID_AUTO, ciphertext, CTLFLAG_WR,
-    &dumperkey.kdk_ciphertext, KERNELDUMP_CIPHERTEXT_SIZE, "",
-    "Encrypted key material and IV");
+SYSCTL_PROC(_security_ekcd, OID_AUTO, encryptedkey, CTLTYPE_OPAQUE | CTLFLAG_WR,
+    NULL, 0, kerneldump_sysctl_encryptedkey, "", "Encrypted key material");
 #endif /* EKCD */
 
 /*
@@ -849,56 +856,87 @@
 
 #ifdef EKCD
 static int
-kerneldump_sysctl_keymaterial(SYSCTL_HANDLER_ARGS)
+kerneldump_crypto_init(struct dumperinfo *di, struct kerneldumpcrypto *kdc,
+    struct kerneldumpkey *kdk)
 {
 	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);
+	if (kdc == NULL) {
+		printf("Attempt to use an invalid kernel dump crypto.");
+		return (EINVAL);
 	}
 
+	error = rijndael_makeKey(&kdc->kdc_ki, DIR_ENCRYPT,
+	    8 * KERNELDUMP_KEY_SIZE, kdc->kdc_key);
+	if (error <= 0)
+		return (EINVAL);
+
+	error = rijndael_cipherInit(&kdc->kdc_ci, MODE_CBC, kdc->kdc_iv);
+	if (error <= 0)
+		return (EINVAL);
+
+	kdc->kdc_offset = 0;
+	kdc->kdc_bufused = 0;
+
+	di->kdc = kdc;
+	di->kdk = kdk;
+
 	return (0);
 }
 
 static int
-kerneldump_sysctl_iv(SYSCTL_HANDLER_ARGS)
+kerneldump_sysctl_keymaterial(SYSCTL_HANDLER_ARGS)
 {
 	int error;
 
-	error = sysctl_handle_opaque(oidp, &dumperkey.kdk_iv,
-	    KERNELDUMP_IV_SIZE, req);
-	if (error != 0)
+	error = sysctl_handle_opaque(oidp, dumpcrypto.kdc_key,
+	    sizeof(dumpcrypto.kdc_key), req);
+	if (req->newptr == NULL || error != 0)
 		return (error);
 
-	if (req->newptr != NULL) {
-		rijndael_cipherInit(&dumperkey.kdk_ci, MODE_CBC,
-		    dumperkey.kdk_iv);
-	}
+	arc4rand(dumpcrypto.kdc_iv, sizeof(dumpcrypto.kdc_iv), 0);
 
-	return (0);
+	return (kerneldump_crypto_init(&dumper, &dumpcrypto, dumpkey));
 }
 
-static void
-kerneldump_crypto_init(struct dumperinfo *di, struct kerneldumpkey *kdk,
-    struct kerneldumpbuffer *kdb)
+static int
+kerneldump_sysctl_encryptedkey(SYSCTL_HANDLER_ARGS)
 {
+	struct kerneldumpkey *kdk;
+	size_t kdksize;
+	int error;
 
-	if (kdk == NULL || kdb == NULL) {
-		printf("Attempt to use an invalid kernel dump key or buffer.");
-		return;
+	if (req->newptr == NULL) {
+		if (dumpkey == NULL)
+			return (0);
+
+		return (sysctl_handle_opaque(oidp, dumpkey->kdk_encryptedkey,
+		    dumpkey->kdk_encryptedkeylen, req));
 	}
 
-	bzero(kdk, sizeof(struct kerneldumpkey));
-	bzero(kdb, sizeof(struct kerneldumpbuffer));
+	kdksize = ((sizeof(*kdk) + req->newlen + KERNELDUMP_BLOCK_SIZE - 1) /
+	    KERNELDUMP_BLOCK_SIZE) * KERNELDUMP_BLOCK_SIZE;
 
-	di->kdk = kdk;
-	di->kdb = kdb;
+	kdk = (struct kerneldumpkey *)malloc(kdksize, M_KDK, M_WAITOK);
+	if (kdk == NULL)
+		return (ENOMEM);
+
+	kdk->kdk_size = kdksize;
+	bcopy(dumpcrypto.kdc_iv, kdk->kdk_iv, sizeof(kdk->kdk_iv));
+	kdk->kdk_encryptedkeylen = req->newlen;
+
+	error = sysctl_handle_opaque(oidp, kdk->kdk_encryptedkey,
+	    kdk->kdk_encryptedkeylen, req);
+	if (error != 0) {
+		free(kdk, M_KDK);
+		return (error);
+	}
+
+	free(dumpkey, M_KDK);
+	dumpkey = kdk;
+	dumper.kdk = dumpkey;
+
+	return (0);
 }
 #endif /* EKCD */
 
@@ -927,7 +965,9 @@
 	dumper = *di;
 
 #ifdef EKCD
-	kerneldump_crypto_init(&dumper, &dumperkey, &dumperbuffer);
+	error = kerneldump_crypto_init(&dumper, &dumpcrypto, dumpkey);
+	if (error != 0)
+		return (error);
 #endif
 
 	wantcopy = strlcpy(dumpdevname, devname, sizeof(dumpdevname));
@@ -943,64 +983,54 @@
 dump_encrypted_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
     off_t offset, size_t length)
 {
+	struct kerneldumpcrypto *kdc;
 	struct kerneldumpkey *kdk;
-	struct kerneldumpbuffer *kdb;
 	int error;
 	size_t len;
 
+	kdc = di->kdc;
 	kdk = di->kdk;
-	kdb = di->kdb;
 
 	/* Data have to be written continuously. */
-	if (kdb->kdb_offset != 0 && kdb->kdb_offset != offset &&
-	    kdb->kdb_offset + kdb->kdb_used != offset) {
+	if (kdc->kdc_offset != 0 && kdc->kdc_offset != offset &&
+	    kdc->kdc_offset + kdc->kdc_bufused != offset) {
 		return (EINVAL);
 	}
 
-	/* Write kernel dump headers. */
-	if (kdb->kdb_offset == 0 || kdb->kdb_offset == di->mediaoffset +
-	    di->mediasize - sizeof(struct kerneldumpheader)) {
-		kdb->kdb_offset = offset + length;
-		return (di->dumper(di->priv, virtual, physical, offset,
-		    length));
-	}
-
-	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;
+	while (kdc->kdc_bufused + length >= KERNELDUMP_BUFFER_SIZE) {
+		len = KERNELDUMP_BUFFER_SIZE - kdc->kdc_bufused;
+		memcpy(kdc->kdc_buf + kdc->kdc_bufused, virtual, len);
+		kdc->kdc_bufused += len;
 
-		error = rijndael_blockEncrypt(&kdk->kdk_ci, &kdk->kdk_ki,
-		    kdb->kdb_buf, 8 * KERNELDUMP_BUFFER_SIZE, kdb->kdb_buf);
+		error = rijndael_blockEncrypt(&kdc->kdc_ci, &kdc->kdc_ki,
+		    kdc->kdc_buf, 8 * KERNELDUMP_BUFFER_SIZE, kdc->kdc_buf);
 		if (error <= 0)
 			return (EIO);
-		error = rijndael_cipherInit(&kdk->kdk_ci, MODE_CBC,
-		    kdb->kdb_buf + KERNELDUMP_BUFFER_SIZE - KERNELDUMP_IV_SIZE);
+		error = rijndael_cipherInit(&kdc->kdc_ci, MODE_CBC,
+		    kdc->kdc_buf + KERNELDUMP_BUFFER_SIZE - KERNELDUMP_IV_SIZE);
 		if (error <= 0)
 			return (EIO);
 
-		error = di->dumper(di->priv, kdb->kdb_buf, physical,
-		    kdb->kdb_offset, KERNELDUMP_BUFFER_SIZE);
+		error = di->dumper(di->priv, kdc->kdc_buf, physical,
+		    kdc->kdc_offset, KERNELDUMP_BUFFER_SIZE);
 		if (error != 0)
 			return (error);
 
-		kdb->kdb_used = 0;
-		kdb->kdb_offset += KERNELDUMP_BUFFER_SIZE;
+		kdc->kdc_bufused = 0;
+		kdc->kdc_offset += KERNELDUMP_BUFFER_SIZE;
 		virtual = (void *)((char *)virtual + len);
 		length -= len;
 	}
 	if (length > 0) {
-		memcpy(kdb->kdb_buf + kdb->kdb_used, virtual, length);
-		kdb->kdb_used += length;
+		memcpy(kdc->kdc_buf + kdc->kdc_bufused, virtual, length);
+		kdc->kdc_bufused += length;
 	}
 
 	return (0);
 }
 
-/* Call dumper with bounds checking. */
-int
-dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
-    off_t offset, size_t length)
+static int
+dump_check_bounds(struct dumperinfo *di, off_t offset, size_t length)
 {
 
 	if (length != 0 && (offset < di->mediaoffset ||
@@ -1011,8 +1041,23 @@
 		    (uintmax_t)length, (intmax_t)di->mediasize);
 		return (ENOSPC);
 	}
+
+	return (0);
+}
+
+/* Call dumper with bounds checking. */
+int
+dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
+    off_t offset, size_t length)
+{
+	int error;
+
+	error = dump_check_bounds(di, offset, length);
+	if (error != 0)
+		return (error);
+
 #ifdef EKCD
-	if (di->kdk->kdk_enable == 1) {
+	if (di->kdc->kdc_enable == 1) {
 		return (dump_encrypted_write(di, virtual, physical, offset,
 		    length));
 	}
@@ -1020,9 +1065,50 @@
 	return (di->dumper(di->priv, virtual, physical, offset, length));
 }
 
+int
+dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
+    vm_offset_t physical, off_t offset)
+{
+	int error;
+
+	error = dump_check_bounds(di, offset, sizeof(*kdh));
+	if (error != 0)
+		return (error);
+
+	error = di->dumper(di->priv, kdh, physical, offset, sizeof(*kdh));
+	if (error != 0)
+		return (error);
+
+	if (di->kdc->kdc_enable == 1)
+		di->kdc->kdc_offset = offset + sizeof(*kdh);
+
+	return (0);
+}
+
+int
+dump_write_key(struct dumperinfo *di, struct kerneldumpkey *kdk,
+    vm_offset_t physical, off_t offset)
+{
+	int error;
+
+	error = dump_check_bounds(di, offset, kerneldumpkey_size(kdk));
+	if (error != 0)
+		return (error);
+
+	error = di->dumper(di->priv, kdk, physical, offset,
+	    kerneldumpkey_size(kdk));
+	if (error != 0)
+		return (error);
+
+	if (di->kdc->kdc_enable == 1)
+		di->kdc->kdc_offset = offset + kerneldumpkey_size(kdk);
+
+	return (0);
+}
+
 void
 mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver,
-    uint64_t dumplen, uint32_t blksz)
+    uint64_t dumplen, uint32_t dumpkeysize, uint32_t blksz)
 {
 
 	bzero(kdh, sizeof(*kdh));
@@ -1032,14 +1118,11 @@
 	kdh->architectureversion = htod32(archver);
 	kdh->dumplength = htod64(dumplen);
 	kdh->dumptime = htod64(time_second);
+	kdh->dumpkeysize = htod32(dumpkeysize);
 	kdh->blocksize = htod32(blksz);
 	strncpy(kdh->hostname, prison0.pr_hostname, sizeof(kdh->hostname));
 	strncpy(kdh->versionstring, version, sizeof(kdh->versionstring));
 	if (panicstr != NULL)
 		strncpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
-#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	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sys/sys/conf.h	Sun Jun  7 11:49:59 2015	(r286773)
@@ -309,8 +309,9 @@
 EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn);
 
 /* EKCD structures. */
+struct kerneldumpheader;
+struct kerneldumpcrypto;
 struct kerneldumpkey;
-struct kerneldumpbuffer;
 
 struct dumperinfo {
 	dumper_t *dumper;	/* Dumping function. */
@@ -319,12 +320,16 @@
 	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. */
+	struct kerneldumpcrypto	*kdc; /* Kernel dump crypto. */
+	struct kerneldumpkey	*kdk; /* Kernel dump key. */
 };
 
 int set_dumper(struct dumperinfo *, const char *_devname, struct thread *td);
 int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t);
+int dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
+    vm_offset_t physical, off_t offset);
+int dump_write_key(struct dumperinfo *di, struct kerneldumpkey *kdk,
+    vm_offset_t physical, off_t offset);
 int doadump(boolean_t);
 extern int dumping;		/* system is dumping */
 

Modified: soc2013/def/crashdump-head/sys/sys/kerneldump.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/kerneldump.h	Sun Jun  7 10:57:02 2015	(r286772)
+++ soc2013/def/crashdump-head/sys/sys/kerneldump.h	Sun Jun  7 11:49:59 2015	(r286773)
@@ -56,8 +56,8 @@
 #define	htod64(x)	(x)
 #endif
 
+#define	KERNELDUMP_BLOCK_SIZE		512
 #define	KERNELDUMP_BUFFER_SIZE		1024
-#define	KERNELDUMP_CIPHERTEXT_SIZE	512
 #define	KERNELDUMP_IV_SIZE		16
 #define	KERNELDUMP_KEY_SIZE		32
 
@@ -85,14 +85,29 @@
 #define	KERNELDUMP_TEXT_VERSION		1
 	uint64_t	dumplength;		/* excl headers */
 	uint64_t	dumptime;
+	uint32_t	dumpkeysize;
 	uint32_t	blocksize;
 	char		hostname[64];
 	char		versionstring[192];
 	char		panicstring[192];
-	char		ciphertext[KERNELDUMP_CIPHERTEXT_SIZE];
 	uint32_t	parity;
+	char		pad[508];
 };
 
+struct kerneldumpkey {
+	uint32_t	kdk_size;
+	uint8_t		kdk_iv[KERNELDUMP_IV_SIZE];
+	int		kdk_encryptedkeylen;
+	uint8_t		kdk_encryptedkey[];
+};
+
+static __inline size_t
+kerneldumpkey_size(struct kerneldumpkey *kdk)
+{
+
+	return (kdk->kdk_size);
+}
+
 /*
  * Parity calculation is endian insensitive.
  */
@@ -110,28 +125,13 @@
 }
 
 #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;
 };
 
 void mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver,
-    uint64_t dumplen, uint32_t blksz);
+    uint64_t dumplen, uint32_t dumpkeysize, uint32_t blksz);
 
 int dumpsys_generic(struct dumperinfo *);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506071150.t57Bo0CT042516>