socsvn commit: r257635 - in soc2013/def/crashdump-head: etc/rc.d sbin/dumpkey
def at FreeBSD.org
def at FreeBSD.org
Mon Sep 23 04:40:35 UTC 2013
Author: def
Date: Mon Sep 23 04:40:34 2013
New Revision: 257635
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257635
Log:
Change dumpkey to decrypt a crash dump with a custom XTS-AES key and a RSA key.
Modified:
soc2013/def/crashdump-head/etc/rc.d/dumpkey
soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c
Modified: soc2013/def/crashdump-head/etc/rc.d/dumpkey
==============================================================================
--- soc2013/def/crashdump-head/etc/rc.d/dumpkey Mon Sep 23 04:20:37 2013 (r257634)
+++ soc2013/def/crashdump-head/etc/rc.d/dumpkey Mon Sep 23 04:40:34 2013 (r257635)
@@ -29,7 +29,7 @@
dumpkey_start()
{
- /sbin/dumpkey -p ${dumpkey_pub}
+ /sbin/dumpkey -e ${dumpkey_pub}
}
dumpkey_predecrypt()
Modified: soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c
==============================================================================
--- soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c Mon Sep 23 04:20:37 2013 (r257634)
+++ soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c Mon Sep 23 04:40:34 2013 (r257635)
@@ -13,6 +13,7 @@
#include <openssl/pem.h>
#define PATH_DEVRANDOM "/dev/random"
+#define PEFS_SECTOR_SIZE 4096
static void
hkdf_expand(struct xts_ctx *ctx, const uint8_t *masterkey, uint8_t *key,
@@ -31,15 +32,17 @@
static void
usage(void)
{
- printf("usage: dumpkey -p public_key\n");
+ printf("%s\n%s\n",
+ "usage: dumpkey -e public_key",
+ " dumpkey -d private_key -k encrypted_key -c encrypted_core");
}
static int
-random_data(char *buf, size_t size)
+read_data(char *buf, size_t size, char *fname)
{
FILE *fp;
- fp = fopen(PATH_DEVRANDOM, "r");
+ fp = fopen(fname, "r");
if (fp == NULL)
return (-1);
@@ -56,6 +59,12 @@
}
static int
+random_data(char *buf, size_t size)
+{
+ return (read_data(buf, size, PATH_DEVRANDOM));
+}
+
+static int
encrypt_key(char *plainkey, struct kerneldumpkey *key, RSA *public_key, char *public_key_file)
{
FILE *fp;
@@ -83,6 +92,33 @@
}
static int
+decrypt_key(char *cipherkey, char *key, char *tweak, RSA *private_key, char *private_key_file)
+{
+ FILE *fp;
+ char buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE];
+
+ fp = fopen(private_key_file, "r");
+
+ if (fp == NULL)
+ return (-1);
+
+ private_key = PEM_read_RSAPrivateKey(fp, &private_key, NULL, NULL);
+ fclose(fp);
+
+ if (private_key == NULL)
+ return (-1);
+
+ if (RSA_private_decrypt(KERNELDUMP_ENCRYPTED_KEY_SIZE, cipherkey, buf,
+ private_key, RSA_PKCS1_PADDING) == -1)
+ return (-1);
+
+ memcpy(key, buf, KERNELDUMP_KEY_SIZE);
+ memcpy(tweak, buf + KERNELDUMP_KEY_SIZE, KERNELDUMP_TWEAK_SIZE);
+
+ return (0);
+}
+
+static int
expand_key(char *masterkey, struct xts_ctx *data_ctx, struct xts_ctx *tweak_ctx)
{
struct xts_ctx ctx;
@@ -111,74 +147,165 @@
return (sysctlbyname("kern.dumpkey", NULL, NULL, key, sizeof(struct kerneldumpkey)));
}
-int
-main(int argc, char **argv)
+static void
+generate_key(char *public_key_file)
{
+ char buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE];
struct kerneldumpkey key;
- char *public_key_file, buf[KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE];
- int ch, error;
RSA *public_key;
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
- OPENSSL_config(NULL);
-
- error = 0;
- public_key_file = NULL;
public_key = RSA_new();
- while ((ch = getopt(argc, argv, "p:")) != -1)
- switch (ch) {
- case 'p':
- public_key_file = optarg;
- break;
- default:
- usage();
- error = 1;
- goto out;
- }
-
- if (public_key_file == NULL) {
- usage();
- error = 1;
- goto out;
- }
-
if (random_data(buf, KERNELDUMP_KEY_SIZE)) {
printf("Error: cannot generate a symmetric key.\n");
- error = 1;
goto out;
}
if (random_data(key.tweak, KERNELDUMP_TWEAK_SIZE)) {
printf("Error: cannot generate a tweak.\n");
- error = 1;
goto out;
}
if (expand_key(buf, &key.data_ctx, &key.tweak_ctx)) {
- printf("Error: cannot expand a symmetric key.");
- error = 1;
+ printf("Error: cannot expand a symmetric key.\n");
goto out;
}
if (encrypt_key(buf, &key, public_key, public_key_file)) {
- printf("Error: cannot encrypt a symmetric key.\n");
- error = 1;
+ printf("Error: cannot encrypt a key.\n");
goto out;
}
if (sysctl_dumpkey(&key)) {
printf("Error: cannot set a kernel crash dump key.\n");
- error = 1;
goto out;
}
out:
bzero(&key, sizeof(struct kerneldumpkey));
- bzero(buf, KERNELDUMP_KEY_SIZE);
+ bzero(buf, KERNELDUMP_KEY_SIZE + KERNELDUMP_TWEAK_SIZE);
RSA_free(public_key);
+}
+
+static void
+decrypt_core(char *encrypted_core, char *private_key_file, char *encrypted_key_file)
+{
+ char key[KERNELDUMP_KEY_SIZE], tweak[KERNELDUMP_TWEAK_SIZE];
+ char buf[PEFS_SECTOR_SIZE];
+ struct xts_ctx data_ctx, tweak_ctx;
+ RSA *private_key;
+ int buf_used, offset;
+ size_t bytes;
+ FILE *fp, *fp_w;
+
+ private_key = RSA_new();
+
+ memcpy(buf, encrypted_core, strlen(encrypted_core) + 1);
+ strcat(buf, "-decrypted");
+ fp = fopen(encrypted_core, "r");
+ fp_w = fopen(buf, "w");
+
+ if (fp == NULL || fp_w == NULL)
+ goto out;
+
+ if (read_data(buf, KERNELDUMP_ENCRYPTED_KEY_SIZE, encrypted_key_file)) {
+ printf("Error: cannot read an encrypted key.\n");
+ goto out;
+ }
+
+ if (decrypt_key(buf, key, tweak, private_key, private_key_file)) {
+ printf("Error: cannot decrypt a key.\n");
+ goto out;
+ }
+
+ if (expand_key(key, &data_ctx, &tweak_ctx)) {
+ printf("Error: cannot expand a symmetric key.\n");
+ goto out;
+ }
+
+ offset = buf_used = 0;
+ do {
+ bytes = fread(buf + buf_used, 1, PEFS_SECTOR_SIZE - buf_used, fp);
+ buf_used += bytes;
+
+ if (buf_used == PEFS_SECTOR_SIZE || (buf_used > 0 && bytes == 0)) {
+ xts_block_decrypt(&xts_alg_aes, &tweak_ctx, &data_ctx, offset, tweak, 0, buf_used, buf, buf);
+
+ if (fwrite(buf, 1, buf_used, fp_w) != buf_used)
+ goto out;
+
+ offset += buf_used;
+ buf_used = 0;
+ }
+ } while (bytes > 0);
+
+out:
+ fclose(fp_w);
+ fclose(fp);
+ bzero(&buf, sizeof(buf));
+ bzero(&key, sizeof(key));
+ bzero(&tweak, sizeof(tweak));
+ bzero(&data_ctx, sizeof(struct xts_ctx));
+ bzero(&tweak_ctx, sizeof(struct xts_ctx));
+ RSA_free(private_key);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *public_key_file, *private_key_file, *encrypted_key_file, *encrypted_core;
+ int ch, error;
+
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+ OPENSSL_config(NULL);
+
+ error = 0;
+ public_key_file = private_key_file = NULL;
+ encrypted_key_file = encrypted_core = NULL;
+
+ while ((ch = getopt(argc, argv, "c:d:e:k:")) != -1)
+ switch (ch) {
+ case 'c':
+ encrypted_core = optarg;
+ break;
+ case 'd':
+ private_key_file = optarg;
+ break;
+ case 'e':
+ public_key_file = optarg;
+ break;
+ case 'k':
+ encrypted_key_file = optarg;
+ break;
+ default:
+ usage();
+ error = 1;
+ goto out;
+ }
+
+ if ((public_key_file == NULL && private_key_file == NULL) ||
+ (public_key_file != NULL && private_key_file != NULL)) {
+ usage();
+ error = 1;
+ goto out;
+ }
+
+ if (private_key_file != NULL && (encrypted_key_file == NULL ||
+ encrypted_core == NULL)) {
+ usage();
+ error = 1;
+ goto out;
+ }
+
+ if (public_key_file != NULL)
+ generate_key(public_key_file);
+
+ if (private_key_file != NULL)
+ decrypt_core(encrypted_core, private_key_file, encrypted_key_file);
+
+out:
ERR_free_strings();
EVP_cleanup();
More information about the svn-soc-all
mailing list