socsvn commit: r255309 - in soc2013/def/crashdump-head: sbin/savecore sys/conf sys/crypto sys/crypto/hmac sys/kern sys/sys

def at FreeBSD.org def at FreeBSD.org
Mon Jul 29 18:21:27 UTC 2013


Author: def
Date: Mon Jul 29 18:21:26 2013
New Revision: 255309
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255309

Log:
  Import pefs' key derivation function. Assume a constant size of tweak.

Added:
  soc2013/def/crashdump-head/sys/crypto/hmac/
  soc2013/def/crashdump-head/sys/crypto/hmac/hmac.c
  soc2013/def/crashdump-head/sys/crypto/hmac/hmac.h
Modified:
  soc2013/def/crashdump-head/sbin/savecore/Makefile
  soc2013/def/crashdump-head/sbin/savecore/decryptfile.c
  soc2013/def/crashdump-head/sbin/savecore/decryptfile.h
  soc2013/def/crashdump-head/sbin/savecore/savecore.c
  soc2013/def/crashdump-head/sys/conf/files
  soc2013/def/crashdump-head/sys/crypto/xts.h
  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/savecore/Makefile
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/Makefile	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sbin/savecore/Makefile	Mon Jul 29 18:21:26 2013	(r255309)
@@ -1,12 +1,14 @@
 # $FreeBSD$
 
 SYS=	${.CURDIR}/../../sys
-.PATH:	${SYS}/crypto/camellia ${SYS}/crypto/rijndael ${SYS}/crypto
+.PATH:	${SYS}/crypto/camellia ${SYS}/crypto/rijndael
+.PATH:	${SYS}/crypto/hmac ${SYS}/crypto/sha2 ${SYS}/crypto
 
 PROG=	savecore
 SRCS=	${PROG}.c decryptfile.c
 SRCS+=	rijndael-api.c rijndael-api-fst.c rijndael-alg-fst.c
 SRCS+=	camellia.c
+SRCS+=	hmac.c sha2.c
 SRCS+=	xts.c
 DPADD=	${LIBZ}
 LDADD=	-lz

Modified: soc2013/def/crashdump-head/sbin/savecore/decryptfile.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/decryptfile.c	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sbin/savecore/decryptfile.c	Mon Jul 29 18:21:26 2013	(r255309)
@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <opencrypto/cryptodev.h>
+#include <crypto/hmac/hmac.h>
 #include "decryptfile.h"
 
 int
@@ -40,9 +42,25 @@
 	return (saved);
 }
 
+void
+hkdf_expand(struct xts_ctx *ctx, const uint8_t *masterkey, uint8_t *key,
+    int idx, const uint8_t *magic, size_t magicsize)
+{
+	uint8_t byte_idx = idx;
+
+	hmac_init(&ctx->o.pctx_hmac, CRYPTO_SHA2_512_HMAC,
+	    masterkey, KERNELDUMP_KEY_SIZE);
+	hmac_update(&ctx->o.pctx_hmac, key, KERNELDUMP_KEY_SIZE);
+	hmac_update(&ctx->o.pctx_hmac, magic, magicsize);
+	hmac_update(&ctx->o.pctx_hmac, &byte_idx, sizeof(byte_idx));
+	hmac_final(&ctx->o.pctx_hmac, key, KERNELDUMP_KEY_SIZE);
+}
+
 FILE *
 dopen(const char *fname, const char *mode, const struct kerneldumpheader *h)
 {
+	uint8_t key[KERNELDUMP_KEY_SIZE];
+	struct xts_ctx ctx;
 	decFile *fd;
 	FILE *fp;
 
@@ -57,16 +75,26 @@
 
 	fd = (decFile *)malloc(sizeof(decFile));
 	fd->fp = fp;
+
 	fd->keysize = h->keysize;
-	memcpy(fd->key, h->key, KERNELDUMP_KEY_SIZE);
-	fd->tweaksize = h->tweaksize;
+	memcpy(fd->key, h->key, fd->keysize);
 	memcpy(fd->tweak, h->tweak, KERNELDUMP_TWEAK_SIZE);
+	bzero(&fd->tweak_ctx, sizeof(fd->tweak_ctx));
+	bzero(&fd->data_ctx, sizeof(fd->data_ctx));
+	bzero(key, KERNELDUMP_KEY_SIZE);
+
+	hkdf_expand(&ctx, fd->key, key, 1, kerneldump_magic, sizeof(kerneldump_magic));
+	xts_alg_aes.pa_keysetup(&fd->data_ctx, key, fd->keysize << 3);
+
+	hkdf_expand(&ctx, fd->key, key, 2, kerneldump_magic, sizeof(kerneldump_magic));
+	xts_alg_aes.pa_keysetup(&fd->tweak_ctx, key, fd->keysize << 3);
+
+	bzero(&ctx, sizeof(ctx));
+	bzero(key, KERNELDUMP_KEY_SIZE);
+
 	fd->offset = 0;
 	fd->buf_used = 0;
 
-	rijndael_set_key(&fd->tweak_ctx, fd->key, fd->keysize << 3);
-	rijndael_set_key(&fd->data_ctx, fd->key, fd->keysize << 3);
-
 	return (funopen(fd, NULL, dwrite, NULL, dclose));
 }
 

Modified: soc2013/def/crashdump-head/sbin/savecore/decryptfile.h
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/decryptfile.h	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sbin/savecore/decryptfile.h	Mon Jul 29 18:21:26 2013	(r255309)
@@ -8,10 +8,9 @@
 	FILE		*fp;
 	int		keysize;
 	char		key[KERNELDUMP_KEY_SIZE];
-	int		tweaksize;
 	char		tweak[KERNELDUMP_TWEAK_SIZE];
-	rijndael_ctx	tweak_ctx;
-	rijndael_ctx	data_ctx;
+	struct xts_ctx	tweak_ctx;
+	struct xts_ctx	data_ctx;
 	off_t		offset;
 #define	PEFS_SECTOR_SIZE	4096
 	char		buf[PEFS_SECTOR_SIZE];

Modified: soc2013/def/crashdump-head/sbin/savecore/savecore.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/savecore/savecore.c	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sbin/savecore/savecore.c	Mon Jul 29 18:21:26 2013	(r255309)
@@ -123,7 +123,6 @@
 	fprintf(f, "  Dump Parity: %u\n", h->parity);
 	fprintf(f, "  Bounds: %d\n", bounds);
 	fprintf(f, "  Key length: %d bits\n", h->keysize << 3);
-	fprintf(f, "  Tweak length: %d bits\n", h->tweaksize << 3);
 
 	switch(status) {
 	case STATUS_BAD:

Modified: soc2013/def/crashdump-head/sys/conf/files
==============================================================================
--- soc2013/def/crashdump-head/sys/conf/files	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sys/conf/files	Mon Jul 29 18:21:26 2013	(r255309)
@@ -537,6 +537,7 @@
 crypto/camellia/camellia-api.c	optional crypto | ipsec
 crypto/des/des_ecb.c		optional crypto | ipsec
 crypto/des/des_setkey.c		optional crypto | ipsec
+crypto/hmac/hmac.c		optional crypto | encrypt_crash
 crypto/rc4/rc4.c		optional netgraph_mppc_encryption | kgssapi
 crypto/rijndael/rijndael-alg-fst.c optional crypto | geom_bde | \
 					 ipsec | random | wlan_ccmp

Added: soc2013/def/crashdump-head/sys/crypto/hmac/hmac.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/def/crashdump-head/sys/crypto/hmac/hmac.c	Mon Jul 29 18:21:26 2013	(r255309)
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <opencrypto/cryptodev.h>
+
+#include <crypto/hmac/hmac.h>
+
+#ifndef _KERNEL
+#define	panic(...)	do {						\
+	fprintf(stderr, __VA_ARGS__);					\
+	abort();							\
+} while (0)
+#endif
+
+typedef void hmac_hash_init_t(union hmac_hash_ctx *ctx);
+typedef void hmac_hash_update_t(union hmac_hash_ctx *ctx, const uint8_t *,
+    size_t);
+typedef void hmac_hash_final_t(uint8_t *, union hmac_hash_ctx *ctx);
+
+struct hmac_hash {
+	u_int			block_len;
+	u_int			digest_len;
+	hmac_hash_init_t	*init;
+	hmac_hash_update_t	*update;
+	hmac_hash_final_t	*final;
+};
+
+static const struct hmac_hash hmac_hash_sha256 = {
+	.block_len =	SHA256_BLOCK_LENGTH,
+	.digest_len =	SHA256_DIGEST_LENGTH,
+	.init =		(hmac_hash_init_t *)&SHA256_Init,
+	.update =	(hmac_hash_update_t *)&SHA256_Update,
+	.final =	(hmac_hash_final_t *)&SHA256_Final,
+};
+
+static const struct hmac_hash hmac_hash_sha384 = {
+	.block_len =	SHA384_BLOCK_LENGTH,
+	.digest_len =	SHA384_DIGEST_LENGTH,
+	.init =		(hmac_hash_init_t *)&SHA384_Init,
+	.update =	(hmac_hash_update_t *)&SHA384_Update,
+	.final =	(hmac_hash_final_t *)&SHA384_Final,
+};
+
+static const struct hmac_hash hmac_hash_sha512 = {
+	.block_len =	SHA512_BLOCK_LENGTH,
+	.digest_len =	SHA512_DIGEST_LENGTH,
+	.init =		(hmac_hash_init_t *)&SHA512_Init,
+	.update =	(hmac_hash_update_t *)&SHA512_Update,
+	.final =	(hmac_hash_final_t *)&SHA512_Final,
+};
+
+void
+hmac_init(struct hmac_ctx *ctx, int algo, const uint8_t *hkey, size_t hkeylen)
+{
+	const struct hmac_hash *hash;
+	u_int i;
+
+	switch (algo) {
+	case CRYPTO_SHA2_256_HMAC:
+		hash = &hmac_hash_sha256;
+		break;
+	case CRYPTO_SHA2_384_HMAC:
+		hash = &hmac_hash_sha384;
+		break;
+	case CRYPTO_SHA2_512_HMAC:
+		hash = &hmac_hash_sha512;
+		break;
+	default:
+		panic("HMAC: invalid alorithm: %d.", algo);
+		return;
+	}
+
+	ctx->hash = hash;
+	bzero(ctx->k_opad, hash->block_len);
+	if (hkeylen == 0)
+		; /* do nothing */
+	else if (hkeylen <= hash->block_len)
+		bcopy(hkey, ctx->k_opad, hkeylen);
+	else {
+		/*
+		 * If key is longer than HMAC_BLOCK_LENGTH_MAX bytes
+		 * reset it to key = HASH(key).
+		 */
+		hash->init(&ctx->hash_ctx);
+		hash->update(&ctx->hash_ctx, hkey, hkeylen);
+		hash->final(ctx->k_opad, &ctx->hash_ctx);
+	}
+
+	/* Perform inner SHA512. */
+	hash->init(&ctx->hash_ctx);
+	/* XOR key ipad value. */
+	for (i = 0; i < hash->block_len; i++)
+		ctx->k_opad[i] ^= 0x36;
+	hash->update(&ctx->hash_ctx, ctx->k_opad, hash->block_len);
+	/* XOR key opad value. */
+	for (i = 0; i < hash->block_len; i++)
+		ctx->k_opad[i] ^= 0x36 ^ 0x5c;
+}
+
+void
+hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
+    size_t datasize)
+{
+
+	ctx->hash->update(&ctx->hash_ctx, data, datasize);
+}
+
+void
+hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize)
+{
+	const struct hmac_hash *hash = ctx->hash;
+	u_char digest[HMAC_DIGEST_LENGTH_MAX];
+
+	if (mdsize == 0 || mdsize > hash->digest_len) {
+		panic("HMAC: invalid digest buffer size: %zu (digest length %u).",
+		    mdsize, hash->digest_len);
+		return;
+	}
+
+	hash->final(digest, &ctx->hash_ctx);
+	/* Perform outer SHA512. */
+	hash->init(&ctx->hash_ctx);
+	hash->update(&ctx->hash_ctx, ctx->k_opad, hash->block_len);
+	hash->update(&ctx->hash_ctx, digest, sizeof(digest));
+	hash->final(digest, &ctx->hash_ctx);
+	bzero(ctx, sizeof(*ctx));
+
+	bcopy(digest, md, mdsize);
+}
+
+void
+hmac(int algo, const uint8_t *hkey, size_t hkeysize, const uint8_t *data,
+    size_t datasize, uint8_t *md, size_t mdsize)
+{
+	struct hmac_ctx ctx;
+
+	hmac_init(&ctx, algo, hkey, hkeysize);
+	hmac_update(&ctx, data, datasize);
+	/* mdsize == 0 means "Give me the whole hash!" */
+	if (mdsize == 0)
+		mdsize = ctx.hash->digest_len;
+	hmac_final(&ctx, md, mdsize);
+}

Added: soc2013/def/crashdump-head/sys/crypto/hmac/hmac.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/def/crashdump-head/sys/crypto/hmac/hmac.h	Mon Jul 29 18:21:26 2013	(r255309)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_CRYPTO_HMAC_H
+#define _SYS_CRYPTO_HMAC_H
+
+#include <crypto/sha2/sha2.h>
+
+#define HMAC_BLOCK_LENGTH_MAX		SHA512_BLOCK_LENGTH
+#define HMAC_DIGEST_LENGTH_MAX		SHA512_DIGEST_LENGTH
+
+struct hmac_hash;
+
+struct hmac_ctx {
+	const struct hmac_hash	*hash;
+	union hmac_hash_ctx {
+		SHA256_CTX	sha256_ctx;
+		SHA384_CTX	sha384_ctx;
+		SHA512_CTX	sha512_ctx;
+	}		hash_ctx;
+	u_char		k_opad[HMAC_BLOCK_LENGTH_MAX];
+};
+
+void hmac_init(struct hmac_ctx *ctx, int algo, const uint8_t *hkey,
+    size_t hkeylen);
+void hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
+    size_t datasize);
+void hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize);
+void hmac(int algo, const uint8_t *hkey, size_t hkeysize,
+    const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize);
+
+#endif /* _SYS_CRYPTO_HMAC_H */

Modified: soc2013/def/crashdump-head/sys/crypto/xts.h
==============================================================================
--- soc2013/def/crashdump-head/sys/crypto/xts.h	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sys/crypto/xts.h	Mon Jul 29 18:21:26 2013	(r255309)
@@ -31,6 +31,7 @@
 
 #include <crypto/camellia/camellia.h>
 #include <crypto/rijndael/rijndael.h>
+#include <crypto/hmac/hmac.h>
 
 #define	XTS_BLK_BYTES		16
 #define	XTS_BLK_MASK		(XTS_BLK_BYTES - 1)
@@ -42,6 +43,7 @@
 	union {
 		camellia_ctx	pctx_camellia;
 		rijndael_ctx	pctx_aes;
+		struct hmac_ctx	pctx_hmac;
 	} o;
 } __aligned(CACHE_LINE_SIZE);
 

Modified: soc2013/def/crashdump-head/sys/kern/kern_shutdown.c
==============================================================================
--- soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sys/kern/kern_shutdown.c	Mon Jul 29 18:21:26 2013	(r255309)
@@ -86,7 +86,7 @@
 
 #include <sys/signalvar.h>
 
-#include <crypto/xts.h>
+#include <opencrypto/cryptodev.h>
 
 #ifndef PANIC_REBOOT_WAIT_TIME
 #define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
@@ -145,8 +145,8 @@
 int dumping;				/* system is dumping */
 int rebooting;				/* system is rebooting */
 static struct dumperinfo dumper;	/* our selected dumper */
-static rijndael_ctx dumper_tweak_ctx;
-static rijndael_ctx dumper_data_ctx;
+static struct kerneldumpkey dumperkey;
+static struct kerneldumpbuffer dumperbuffer;
 
 /* Context information for dump-debuggers. */
 static struct pcb dumppcb;		/* Registers. */
@@ -851,6 +851,8 @@
 	if (dumper.dumper != NULL)
 		return (EBUSY);
 	dumper = *di;
+	dumper.kdk = &dumperkey;
+	dumper.kdb = &dumperbuffer;
 
 	kerneldump_crypto_init(&dumper);
 
@@ -867,6 +869,8 @@
 dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
     off_t offset, size_t length)
 {
+	struct kerneldumpkey *kdk;
+	struct kerneldumpbuffer *kdb;
 	size_t resid;
 	int error;
 
@@ -879,65 +883,126 @@
 		return (ENOSPC);
 	}
 
+	kdk = di->kdk;
+	kdb = di->kdb;
+
 	/* Write kernel dump headers. */
-	if (di->realoffset == 0 || offset == di->mediaoffset + di->mediasize -
+	if (kdb->realoffset == 0 || offset == di->mediaoffset + di->mediasize -
 		sizeof(struct kerneldumpheader)) {
-		di->realoffset = offset + length;
+		kdb->realoffset = offset + length;
 		return (di->dumper(di->priv, virtual, physical, offset, length));
 	}
 
 	/* The last dump_write call in the current crash. */
 	if (virtual == NULL && physical == 0 && offset == 0 && length == 0) {
-		xts_block_encrypt(&xts_alg_aes, di->tweak_ctx, di->data_ctx,
-				di->offset, di->tweak, di->buf_used,
-				di->buf, di->buf);
-		return (di->dumper(di->priv, di->buf, physical, di->realoffset, di->buf_used));
-	}
-
-	while (length + di->buf_used >= DUMPER_BUFSIZE) {
-		resid = DUMPER_BUFSIZE - di->buf_used;
-		memcpy(di->buf + di->buf_used, virtual, resid);
-		di->buf_used += resid;
-
-		xts_block_encrypt(&xts_alg_aes, di->tweak_ctx, di->data_ctx,
-				di->offset, di->tweak, DUMPER_BUFSIZE,
-				di->buf, di->buf);
+		xts_block_encrypt(&xts_alg_aes, &kdk->tweak_ctx, &kdk->data_ctx,
+				kdb->offset, kdk->tweak, kdb->used,
+				kdb->buf, kdb->buf);
+		return (di->dumper(di->priv, di->kdb->buf, physical, kdb->realoffset, kdb->used));
+	}
+
+	while (length + kdb->used >= KERNELDUMP_BUFFER_SIZE) {
+		resid = KERNELDUMP_BUFFER_SIZE - kdb->used;
+		memcpy(kdb->buf + kdb->used, virtual, resid);
+		kdb->used += resid;
+
+		xts_block_encrypt(&xts_alg_aes, &kdk->tweak_ctx, &kdk->data_ctx,
+				kdb->offset, kdk->tweak, KERNELDUMP_BUFFER_SIZE,
+				kdb->buf, kdb->buf);
 
-		error = (di->dumper(di->priv, di->buf, physical, di->realoffset, DUMPER_BUFSIZE));
+		error = (di->dumper(di->priv, kdb->buf, physical, kdb->realoffset, KERNELDUMP_BUFFER_SIZE));
 
 		if (error)
 			return (error);
 
 		virtual = (void *)((char *)virtual + resid);
 		length -= resid;
-		di->buf_used = 0;
-		di->realoffset += resid;
-		di->offset += DUMPER_BUFSIZE;
+		kdb->used = 0;
+		kdb->realoffset += resid;
+		kdb->offset += KERNELDUMP_BUFFER_SIZE;
 	}
 
 	/* We still have less than blocksize of data to dump. */
 	if (length > 0) {
-		memcpy(di->buf + di->buf_used, virtual, length);
-		di->buf_used += length;
+		memcpy(kdb->buf + kdb->used, virtual, length);
+		kdb->used += length;
 	}
 
 	return (0);
 }
 
+static void
+kerneldump_hkdf_expand(struct xts_ctx *ctx, const uint8_t *masterkey, uint8_t *key,
+			int idx, const uint8_t *magic, size_t magicsize)
+{
+	uint8_t byte_idx = idx;
+
+	hmac_init(&ctx->o.pctx_hmac, CRYPTO_SHA2_512_HMAC,
+		masterkey, KERNELDUMP_KEY_SIZE);
+	hmac_update(&ctx->o.pctx_hmac, key, KERNELDUMP_KEY_SIZE);
+	hmac_update(&ctx->o.pctx_hmac, magic, magicsize);
+	hmac_update(&ctx->o.pctx_hmac, &byte_idx, sizeof(byte_idx));
+	hmac_final(&ctx->o.pctx_hmac, key, KERNELDUMP_KEY_SIZE);
+}
+
 void
 kerneldump_crypto_init(struct dumperinfo *di)
 {
+	if (di->kdk == NULL || di->kdb == NULL) {
+		printf("Attempt to initialize a non-existing kernel dump key and buffer.");
+		return;
+	}
+
 	/* In the future the tweak will be set via sysctl. */
-	arc4rand(kerneldumptweak, KERNELDUMP_TWEAK_SIZE, 0);
-	di->key = (char *)kerneldumpkey;
-	di->tweak = kerneldumptweak;
-	di->tweak_ctx = &dumper_tweak_ctx;
-	di->data_ctx = &dumper_data_ctx;
-	di->buf_used = 0;
-	di->realoffset = 0;
-	di->offset = 0;
-	rijndael_set_key(di->tweak_ctx, di->key, KERNELDUMP_KEY_SIZE << 3);
-	rijndael_set_key(di->data_ctx, di->key, KERNELDUMP_KEY_SIZE << 3);
+	arc4rand(kerneldump_tweak, KERNELDUMP_TWEAK_SIZE, 0);
+
+	di->kdk = kerneldump_set_key(di->kdk, KERNELDUMP_KEY_SIZE, kerneldump_key, kerneldump_tweak);
+	di->kdb = kerneldump_set_buffer(di->kdb);
+}
+
+struct kerneldumpkey *
+kerneldump_set_key(struct kerneldumpkey *kdk, int keysize, char *masterkey, char *tweak)
+{
+	uint8_t key[KERNELDUMP_KEY_SIZE];
+	struct xts_ctx ctx;
+
+	if (kdk == NULL) {
+		printf("Cannot initialize kernel dump key.");
+		return (NULL);
+	}
+
+	kdk->keysize = keysize;
+	memcpy(kdk->key, masterkey, kdk->keysize);
+	memcpy(kdk->tweak, tweak, KERNELDUMP_TWEAK_SIZE);
+	bzero(&kdk->tweak_ctx, sizeof(kdk->tweak_ctx));
+	bzero(&kdk->data_ctx, sizeof(kdk->data_ctx));
+	bzero(key, KERNELDUMP_KEY_SIZE);
+
+	kerneldump_hkdf_expand(&ctx, kdk->key, key, 1, kerneldump_magic, sizeof(kerneldump_magic));
+	xts_alg_aes.pa_keysetup(&kdk->data_ctx, key, kdk->keysize << 3);
+
+	kerneldump_hkdf_expand(&ctx, kdk->key, key, 2, kerneldump_magic, sizeof(kerneldump_magic));
+	xts_alg_aes.pa_keysetup(&kdk->tweak_ctx, key, kdk->keysize << 3);
+
+	bzero(&ctx, sizeof(ctx));
+	bzero(key, KERNELDUMP_KEY_SIZE);
+
+	return (kdk);
+}
+
+struct kerneldumpbuffer *
+kerneldump_set_buffer(struct kerneldumpbuffer *kdb)
+{
+	if (kdb == NULL) {
+		printf("Cannot initialize kernel dump buffer.");
+		return (NULL);
+	}
+
+	kdb->used = 0;
+	kdb->realoffset = 0;
+	kdb->offset = 0;
+
+	return (kdb);
 }
 
 void
@@ -957,9 +1022,8 @@
 	strncpy(kdh->versionstring, version, sizeof(kdh->versionstring));
 	if (panicstr != NULL)
 		strncpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
-	kdh->keysize = KERNELDUMP_KEY_SIZE;
-	strncpy(kdh->key, dumper.key, kdh->keysize);
-	kdh->tweaksize = KERNELDUMP_TWEAK_SIZE;
-	strncpy(kdh->tweak, dumper.tweak, kdh->tweaksize);
+	kdh->keysize = dumper.kdk->keysize;
+	strncpy(kdh->key, dumper.kdk->key, kdh->keysize);
+	strncpy(kdh->tweak, dumper.kdk->tweak, KERNELDUMP_TWEAK_SIZE);
 	kdh->parity = kerneldump_parity(kdh);
 }

Modified: soc2013/def/crashdump-head/sys/sys/conf.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/conf.h	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sys/sys/conf.h	Mon Jul 29 18:21:26 2013	(r255309)
@@ -323,7 +323,8 @@
 EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn);
 
 /* Stuff relating to kernel-dump */
-#define	DUMPER_BUFSIZE	4096
+struct kerneldumpkey;
+struct kerneldumpbuffer;
 
 struct dumperinfo {
 	dumper_t *dumper;		/* Dumping function. */
@@ -332,14 +333,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. */
-	char	*key;			/* Key information. */
-	char	*tweak;			/* Tweak. */
-	void	*tweak_ctx;		/* Tweak context. */
-	void	*data_ctx;		/* Data context. */
-	uint8_t buf[DUMPER_BUFSIZE];	/* Raw data buffer. */
-	u_int	buf_used;		/* Number of bytes used in the buffer. */
-	off_t	offset;			/* Last used offset in a xts_block_encrypt call. */
-	off_t	realoffset;		/* Last used offset in a dump_write call. */
+	struct kerneldumpkey *kdk;	/* Kernel dump key. */
+	struct kerneldumpbuffer	*kdb;	/* Kernel dump buffer. */
 };
 
 int set_dumper(struct dumperinfo *, const char *_devname);

Modified: soc2013/def/crashdump-head/sys/sys/kerneldump.h
==============================================================================
--- soc2013/def/crashdump-head/sys/sys/kerneldump.h	Mon Jul 29 18:02:29 2013	(r255308)
+++ soc2013/def/crashdump-head/sys/sys/kerneldump.h	Mon Jul 29 18:21:26 2013	(r255309)
@@ -39,6 +39,7 @@
 #define _SYS_KERNELDUMP_H
 
 #include <machine/endian.h>
+#include <crypto/xts.h>
 
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define	dtoh32(x)	__bswap32(x)
@@ -81,15 +82,16 @@
 	uint64_t	dumptime;
 	uint32_t	blocksize;
 	char		hostname[64];
-	char		versionstring[168];
-	char		panicstring[168];
+	char		versionstring[170];
+	char		panicstring[170];
 	int		keysize;
 	char		key[KERNELDUMP_KEY_SIZE];
-	int		tweaksize;
 	char		tweak[KERNELDUMP_TWEAK_SIZE];
 	uint32_t	parity;
 };
 
+static const char kerneldump_magic[] = "PEFSKEY-V1";
+
 /*
  * Parity calculation is endian insensitive.
  */
@@ -110,15 +112,33 @@
 /*
  * Constant key for kernel crash dumps.
  */
-static const char kerneldumpkey[32] = {
+static char kerneldump_key[KERNELDUMP_KEY_SIZE] = {
 	0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
 	0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
 	0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41
 };
 
-static char kerneldumptweak[KERNELDUMP_TWEAK_SIZE];
+static char kerneldump_tweak[KERNELDUMP_TWEAK_SIZE];
+
+struct kerneldumpkey {
+	int		keysize;
+	char		key[KERNELDUMP_KEY_SIZE];
+	char		tweak[KERNELDUMP_TWEAK_SIZE];
+	struct xts_ctx	data_ctx;
+	struct xts_ctx	tweak_ctx;
+};
+
+struct kerneldumpbuffer {
+#define	KERNELDUMP_BUFFER_SIZE	4096
+	uint8_t buf[KERNELDUMP_BUFFER_SIZE];	/* Raw data buffer. */
+	u_int	used;				/* Number of bytes used in the buffer. */
+	off_t	offset;				/* Last used offset in a xts_block_encrypt call. */
+	off_t	realoffset;			/* Last used offset in a dump_write call. */
+};
 
 void kerneldump_crypto_init(struct dumperinfo *di);
+struct kerneldumpkey *kerneldump_set_key(struct kerneldumpkey *kdk, int keysize, char *key, char *tweak);
+struct kerneldumpbuffer *kerneldump_set_buffer(struct kerneldumpbuffer *kdb);
 
 void mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver,
     uint64_t dumplen, uint32_t blksz);


More information about the svn-soc-all mailing list