From owner-svn-soc-all@FreeBSD.ORG Sat Sep 21 20:45:54 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 141BEC48 for ; Sat, 21 Sep 2013 20:45:54 +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 00B0427E7 for ; Sat, 21 Sep 2013 20:45:54 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r8LKjruV080277 for ; Sat, 21 Sep 2013 20:45:53 GMT (envelope-from def@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r8LKjrKN080274 for svn-soc-all@FreeBSD.org; Sat, 21 Sep 2013 20:45:53 GMT (envelope-from def@FreeBSD.org) Date: Sat, 21 Sep 2013 20:45:53 GMT Message-Id: <201309212045.r8LKjrKN080274@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: r257574 - soc2013/def/crashdump-head/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: Sat, 21 Sep 2013 20:45:54 -0000 Author: def Date: Sat Sep 21 20:45:53 2013 New Revision: 257574 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257574 Log: dumpkey program which generates an AES key, encrypts it with RSA and transfers it to kernel via sysctl. Added: soc2013/def/crashdump-head/sbin/dumpkey/ soc2013/def/crashdump-head/sbin/dumpkey/Makefile soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c Added: soc2013/def/crashdump-head/sbin/dumpkey/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2013/def/crashdump-head/sbin/dumpkey/Makefile Sat Sep 21 20:45:53 2013 (r257574) @@ -0,0 +1,15 @@ +SYS= ${.CURDIR}/../../sys +.PATH: ${SYS}/crypto ${SYS}/crypto/rijndael +.PATH: ${SYS}/crypto/hmac ${SYS}/crypto/sha2 + +PROG= dumpkey +SRCS= ${PROG}.c +SRCS+= rijndael-api.c rijndael-api-fst.c rijndael-alg-fst.c +SRCS+= hmac.c xts.c sha2.c +CFLAGS+=-I${SYS} +DPADD+= ${LIBCRYPTO} +LDADD+= -lcrypto +WARNS?= 2 +NO_MAN= + +.include Added: soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2013/def/crashdump-head/sbin/dumpkey/dumpkey.c Sat Sep 21 20:45:53 2013 (r257574) @@ -0,0 +1,227 @@ +#include +#include +#include +#include +#include +#include +#include + +#define OPENSSL_NO_SHA +#include +#include +#include +#include + +#define PATH_DEVRANDOM "/dev/random" + +static 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); +} + +static void +usage(void) +{ + printf("usage: dumpkey -p public_key\n"); +} + +static int +read_data(char *buf, size_t size, const char *file) +{ + FILE *fp; + + fp = fopen(file, "r"); + + if (fp == NULL) + return (-1); + + if (fread(buf, size, 1, fp) != 1) { + fclose(fp); + + return (-1); + } + + fclose(fp); + + return (0); +} + +static int +random_data(char *buf, size_t size) +{ + if(read_data(buf, size, PATH_DEVRANDOM)) + return (-1); + + return (0); +} + +static int +encrypt_key(char *key, size_t keysize, char *encrypted_key, RSA *public_key, char *public_key_file) +{ + FILE *fp; + + fp = fopen(public_key_file, "r"); + + if (fp == NULL) + return (-1); + + public_key = PEM_read_RSA_PUBKEY(fp, &public_key, NULL, NULL); + fclose(fp); + + if (public_key == NULL) + return (-1); + + if (RSA_public_encrypt(keysize, key, encrypted_key, public_key, RSA_PKCS1_PADDING) == -1) + return (-1); + + return (0); +} + +static int +expand_key(char *key, size_t keysize, char *data_key, char *tweak_key) +{ + struct xts_ctx ctx; + + bzero(&ctx, sizeof(ctx)); + bzero(data_key, keysize); + bzero(tweak_key, keysize); + + hkdf_expand(&ctx, key, data_key, 1, kerneldump_magic, sizeof(kerneldump_magic)); + memcpy(tweak_key, data_key, keysize); + hkdf_expand(&ctx, key, tweak_key, 2, kerneldump_magic, sizeof(kerneldump_magic)); + + bzero(&ctx, sizeof(ctx)); + + return (0); +} + +static int +set_data_key(char *key, size_t keysize) +{ + return (sysctlbyname("kern.dump.key.data", NULL, 0, key, keysize)); +} + +static int +set_tweak_key(char *key, size_t keysize) +{ + return (sysctlbyname("kern.dump.key.tweak", NULL, 0, key, keysize)); +} + +static int +set_encrypted_key(char *key, size_t keysize) +{ + return (sysctlbyname("kern.dump.key.encrypted", NULL, 0, key, keysize)); +} + +static int +set_tweak(char *tweak, size_t tweaksize) +{ + return (sysctlbyname("kern.dump.tweak", NULL, 0, tweak, tweaksize)); +} + +int +main(int argc, char **argv) +{ + char *public_key_file; + char key[KERNELDUMP_KEY_SIZE], encrypted_key[KERNELDUMP_ENCRYPTED_KEY_SIZE]; + char data_key[KERNELDUMP_KEY_SIZE], tweak_key[KERNELDUMP_KEY_SIZE]; + char tweak[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(key, KERNELDUMP_KEY_SIZE)) { + printf("Error: cannot generate a symmetric key.\n"); + error = 1; + goto out; + } + + if (encrypt_key(key, KERNELDUMP_KEY_SIZE, encrypted_key, public_key, public_key_file)) { + printf("Error: cannot encrypt a symmetric key.\n"); + error = 1; + goto out; + } + + if (set_encrypted_key(encrypted_key, KERNELDUMP_ENCRYPTED_KEY_SIZE)) { + printf("Error: cannot set an encrypted symmetric key.\n"); + error = 1; + goto out; + } + + if (expand_key(key, KERNELDUMP_KEY_SIZE, data_key, tweak_key)) { + printf("Error: cannot expand a symmetric key."); + error = 1; + goto out; + } + + if (set_data_key(data_key, KERNELDUMP_KEY_SIZE)) { + printf("Error: cannot set a symmetric data key.\n"); + error = 1; + goto out; + } + + if (set_tweak_key(tweak_key, KERNELDUMP_KEY_SIZE)) { + printf("Error: cannot set a symmetric tweak key."); + error = 1; + goto out; + } + + if (random_data(tweak, KERNELDUMP_TWEAK_SIZE)) { + printf("Error: cannot generate a tweak.\n"); + error = 1; + goto out; + } + + if (set_tweak(tweak, KERNELDUMP_TWEAK_SIZE)) { + printf("Error: cannot set a tweak.\n"); + error = 1; + goto out; + } + +out: + bzero(key, KERNELDUMP_KEY_SIZE); + bzero(encrypted_key, KERNELDUMP_ENCRYPTED_KEY_SIZE); + bzero(data_key, KERNELDUMP_KEY_SIZE); + bzero(tweak_key, KERNELDUMP_KEY_SIZE); + bzero(tweak, KERNELDUMP_TWEAK_SIZE); + RSA_free(public_key); + + ERR_free_strings(); + EVP_cleanup(); + + return (0); +} +