socsvn commit: r286773 - in soc2013/def/crashdump-head: sbin/cryptcore sbin/savecore sys/amd64/amd64 sys/ddb sys/kern sys/sys
def at FreeBSD.org
def at FreeBSD.org
Sun Jun 7 11:50:04 UTC 2015
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 *);
More information about the svn-soc-all
mailing list