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