From owner-svn-soc-all@FreeBSD.ORG Mon Sep 23 04:40:35 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 072E9AB1 for ; Mon, 23 Sep 2013 04:40:35 +0000 (UTC) (envelope-from def@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id E6B642B21 for ; Mon, 23 Sep 2013 04:40:34 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r8N4eYgq088970 for ; Mon, 23 Sep 2013 04:40:34 GMT (envelope-from def@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r8N4eYj2088943 for svn-soc-all@FreeBSD.org; Mon, 23 Sep 2013 04:40:34 GMT (envelope-from def@FreeBSD.org) Date: Mon, 23 Sep 2013 04:40:34 GMT Message-Id: <201309230440.r8N4eYj2088943@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to def@FreeBSD.org using -f From: def@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r257635 - in soc2013/def/crashdump-head: etc/rc.d sbin/dumpkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Sep 2013 04:40:35 -0000 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 #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();