From patchwork Wed Dec 14 18:46:05 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: 9474493 X-Patchwork-Delegate: herbert@gondor.apana.org.au 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 9C4D66021C for ; Wed, 14 Dec 2016 18:48:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8E514286DF for ; Wed, 14 Dec 2016 18:48:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8180F28734; Wed, 14 Dec 2016 18:48:13 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 07CA3286DF for ; Wed, 14 Dec 2016 18:48:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754074AbcLNSqz (ORCPT ); Wed, 14 Dec 2016 13:46:55 -0500 Received: from frisell.zx2c4.com ([192.95.5.64]:51948 "EHLO frisell.zx2c4.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753763AbcLNSqx (ORCPT ); Wed, 14 Dec 2016 13:46:53 -0500 Received: by frisell.zx2c4.com (ZX2C4 Mail Server) with ESMTP id b1de4026; Wed, 14 Dec 2016 18:40:13 +0000 (UTC) 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=V08d fYy7eKo0hvn2PP2RxDZosLU=; b=w383Pic/2fNHz7/rfmvMPiwprwsCBVH9Bmr1 Pqja2OskYGNQaQ39vQia1Ta9GdkFxEJb12wotHdvLRK5Ocu4z0zTGI5SKBGOejWA 8lvzMIQuMQmnph7DigXEtJ5YpdFY4V43Hf3pKzJWumERKfHYbx1lnq3HepJw5Eg/ IhR2YVfcX3NmVihtP4EzSn+BLiVfik4572NzD1sR2eGvk0wutxBTu7qozk1s1/4b yupt6lRHq9CeOZ914S2Jh1yi+LyRX5n/fW+nR9PsyIkTx6wsox91ODHzWsF4FA54 CVEu28BiPiHAfksvGW9IAHVPWxnyfNRQeXcTRK6PyNbYHr4vtg== Received: by frisell.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 1b9dfb5d (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256:NO); Wed, 14 Dec 2016 18:40:13 +0000 (UTC) From: "Jason A. Donenfeld" To: Netdev , kernel-hardening@lists.openwall.com, LKML , linux-crypto@vger.kernel.org Cc: "Jason A. Donenfeld" , Jean-Philippe Aumasson , Ted Tso Subject: [PATCH v3 3/3] random: use siphash24 instead of md5 for get_random_int/long Date: Wed, 14 Dec 2016 19:46:05 +0100 Message-Id: <20161214184605.24006-3-Jason@zx2c4.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20161214184605.24006-1-Jason@zx2c4.com> References: <20161214035927.30004-1-Jason@zx2c4.com> <20161214184605.24006-1-Jason@zx2c4.com> Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org 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 Cc: Ted Tso --- Changes from v2->v3: - Structs are no longer packed, to mitigate slow byte-by-byte assignment. drivers/char/random.c | 52 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index d6876d506220..b1c2e3b26430 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] __aligned(SIPHASH24_ALIGNMENT); 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,26 @@ static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash) */ unsigned int get_random_int(void) { - __u32 *hash; unsigned int ret; + struct { + u64 chaining; + unsigned long ts; + unsigned long entropy; + pid_t pid; + char end[]; + } __aligned(SIPHASH24_ALIGNMENT) combined; + u64 *chaining; 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_ptr(&get_random_int_chaining); + combined.chaining = *chaining; + combined.ts = jiffies; + combined.entropy = random_get_entropy(); + combined.pid = current->pid; + ret = *chaining = siphash24((u8 *)&combined, offsetof(typeof(combined), end), random_int_secret); + put_cpu_ptr(chaining); return ret; } EXPORT_SYMBOL(get_random_int); @@ -2083,19 +2090,26 @@ EXPORT_SYMBOL(get_random_int); */ unsigned long get_random_long(void) { - __u32 *hash; unsigned long ret; + struct { + u64 chaining; + unsigned long ts; + unsigned long entropy; + pid_t pid; + char end[]; + } __aligned(SIPHASH24_ALIGNMENT) combined; + u64 *chaining; 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_ptr(&get_random_int_chaining); + combined.chaining = *chaining; + combined.ts = jiffies; + combined.entropy = random_get_entropy(); + combined.pid = current->pid; + ret = *chaining = siphash24((u8 *)&combined, offsetof(typeof(combined), end), random_int_secret); + put_cpu_ptr(chaining); return ret; } EXPORT_SYMBOL(get_random_long);