From patchwork Wed Dec 14 03:10:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 9473665 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CD0256021C for ; Wed, 14 Dec 2016 03:11:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C5477286D6 for ; Wed, 14 Dec 2016 03:11:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B9B5A286E3; Wed, 14 Dec 2016 03:11:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id D8514286D6 for ; Wed, 14 Dec 2016 03:11:09 +0000 (UTC) Received: (qmail 30239 invoked by uid 550); 14 Dec 2016 03:11:07 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: kernel-hardening@lists.openwall.com Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 30203 invoked from network); 14 Dec 2016 03:11:05 -0000 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=zx2c4.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=mail; bh=/4Ji jgJztWlSu+OHOToQoP3jdts=; b=BDJvgp7nZRUTIjX8JXZkpeOSfGYL7Hi8TL5h aOTEE6qz+1I9FdvSnGN9KfaSmlKSit6cbiHtXTeEj30U6PepiOYyC3cWjQR3wBNI AswSM2x4NKhJBKNcgYLMDmnrR2Dqwf22nCkZ9BNIyNmST861hXw8DomlfKJVj6pi CweifxAm+96MBtq0HSyvGurAqsQoav8FFVWC+ULtU5sdRx+KdVyabkguJwzO9azn 7jlFFH1ajBgt0SYPJpycqZ7/30Ii8ezJ53pBwxuFVRAAp0ytEh5dw+5Ii15B2xT1 gx4YztP9aNWgqgsLIS2cw0aAxVXDJoDS+aYqQfjhaUDrbzYbvA== From: "Jason A. Donenfeld" To: Netdev , David Miller , Linus Torvalds , "kernel-hardening@lists.openwall.com" , LKML , George Spelvin , Scott Bauer , Andi Kleen , Andy Lutomirski , Greg KH , Eric Biggers , linux-crypto@vger.kernel.org, Ted Tso Cc: "Jason A. Donenfeld" , Jean-Philippe Aumasson Date: Wed, 14 Dec 2016 04:10:37 +0100 Message-Id: <20161214031037.25498-1-Jason@zx2c4.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20161214001656.19388-1-Jason@zx2c4.com> References: <20161214001656.19388-1-Jason@zx2c4.com> Subject: [kernel-hardening] [PATCH 4/3] random: use siphash24 instead of md5 for get_random_int/long X-Virus-Scanned: ClamAV using ClamSMTP This duplicates the current algorithm for get_random_int/long, but uses siphash24 instead. This comes with several benefits. It's certainly faster and more cryptographically secure than MD5. This patch also hashes the pid, entropy, and timestamp as fixed width fields, in order to increase diffusion. The previous md5 algorithm used a per-cpu md5 state, which caused successive calls to the function to chain upon each other. While it's not entirely clear that this kind of chaining is absolutely necessary when using a secure PRF like siphash24, it can't hurt, and the timing of the call chain does add a degree of natural entropy. So, in keeping with this design, instead of the massive per-cpu 64-byte md5 state, there is instead a per-cpu previously returned value for chaining. Signed-off-by: Jason A. Donenfeld Cc: Jean-Philippe Aumasson --- drivers/char/random.c | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index d6876d506220..25f96f074da5 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -262,6 +262,7 @@ #include #include #include +#include #include #include @@ -2042,7 +2043,7 @@ struct ctl_table random_table[] = { }; #endif /* CONFIG_SYSCTL */ -static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; +static u8 random_int_secret[SIPHASH24_KEY_LEN]; int random_int_secret_init(void) { @@ -2050,8 +2051,7 @@ int random_int_secret_init(void) return 0; } -static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash) - __aligned(sizeof(unsigned long)); +static DEFINE_PER_CPU(u64, get_random_int_chaining); /* * Get a random word for internal kernel use only. Similar to urandom but @@ -2061,19 +2061,25 @@ static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash) */ unsigned int get_random_int(void) { - __u32 *hash; + uint64_t *chaining; unsigned int ret; + struct { + uint64_t chaining; + unsigned long ts; + unsigned long entropy; + pid_t pid; + } __packed combined; if (arch_get_random_int(&ret)) return ret; - hash = get_cpu_var(get_random_int_hash); - - hash[0] += current->pid + jiffies + random_get_entropy(); - md5_transform(hash, random_int_secret); - ret = hash[0]; - put_cpu_var(get_random_int_hash); - + chaining = &get_cpu_var(get_random_int_chaining); + combined.chaining = *chaining; + combined.ts = jiffies; + combined.entropy = random_get_entropy(); + combined.pid = current->pid; + ret = *chaining = siphash24((u8 *)&combined, sizeof(combined), random_int_secret); + put_cpu_var(chaining); return ret; } EXPORT_SYMBOL(get_random_int); @@ -2083,19 +2089,25 @@ EXPORT_SYMBOL(get_random_int); */ unsigned long get_random_long(void) { - __u32 *hash; + uint64_t *chaining; unsigned long ret; + struct { + uint64_t chaining; + unsigned long ts; + unsigned long entropy; + pid_t pid; + } __packed combined; if (arch_get_random_long(&ret)) return ret; - hash = get_cpu_var(get_random_int_hash); - - hash[0] += current->pid + jiffies + random_get_entropy(); - md5_transform(hash, random_int_secret); - ret = *(unsigned long *)hash; - put_cpu_var(get_random_int_hash); - + chaining = &get_cpu_var(get_random_int_chaining); + combined.chaining = *chaining; + combined.ts = jiffies; + combined.entropy = random_get_entropy(); + combined.pid = current->pid; + ret = *chaining = siphash24((u8 *)&combined, sizeof(combined), random_int_secret); + put_cpu_var(chaining); return ret; } EXPORT_SYMBOL(get_random_long);