Date: Wed, 29 Apr 2015 09:34:58 GMT From: def@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: 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 Message-ID: <201504290934.t3T9YwpD013611@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504290934.t3T9YwpD013611>