From patchwork Mon Jun 18 23:43:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jason A. Donenfeld" X-Patchwork-Id: 139067 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp4535419lji; Mon, 18 Jun 2018 16:43:59 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJwvGcnwE28yZVxxMQeA4qwHmkWHeseeW82ZpanEvRlGlt22qGNjqrDRo7QNo2zhYodLyw4 X-Received: by 2002:a63:7781:: with SMTP id s123-v6mr12931806pgc.117.1529365439839; Mon, 18 Jun 2018 16:43:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529365439; cv=none; d=google.com; s=arc-20160816; b=SavSmRhF6yM65B5IC224as4N6EiB9CFEcIls73ROugPRCGgHGodA3tNh+4aAEetF5y f/R2D2YfqEqWTH+UHaW5/2445+cWQVB+ViqQvDfX4z37b0bTpkKwZxZkgtMhnh2cZLCX L5QbSjQdCkxgrCEdjql4dyBTv+hGycJa5wYRouqXtanYfpFmBA47ieRd0qPYNx2Yejj8 xQHywhwrH5kkIrRSoHE+I7Nndydcl1YwiFAf4qYRI/QC8D2wew1widZMY/3/EjvoUgl6 cxply+Uq8GvDPppZdVwRFhEyOjPiLHbTrkSr0eV3WOzhHqjqK9Zmyzvv8+m8PwYIIbya FB3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=lA+mTAnoREKjduZ4CPml8vKkc+eQwnQDxhAG/SjepOE=; b=A1RjXPTb5W7B3qyyuDhh2ZXy0hxdZ9kw3GTV0GfU/wUauyTN1h6i+wJxNr5Pnz6fEy NFgiapnG58t+WXRNZ0fiWU1G78a4E7Jzxm4Pq0iN7b04YTmZrwbz0mVuAGC3/V6M9VYV 3Jljn4AJvPFTl/7DjbOHwI0DjSbmWHBtqtCMOVRUttsNkcV2aUooa01RGZptI9WG4FD1 YOyCZUseQPVPXYn32XFPFhi+VF4nd70i/10PlPCWTRQ+K1C5amAezDsDVkk4QOrA0796 2mdQxctsv+jYN4unHITd030KzR21QpDA5+Us1TZRa4jouCGmN1CrXr1lMDtP3jTsBVm7 afrQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@zx2c4.com header.s=mail header.b=1kJhLxuP; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zx2c4.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f3-v6si9687548plr.214.2018.06.18.16.43.59; Mon, 18 Jun 2018 16:43:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@zx2c4.com header.s=mail header.b=1kJhLxuP; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zx2c4.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964926AbeFRXn5 (ORCPT + 30 others); Mon, 18 Jun 2018 19:43:57 -0400 Received: from frisell.zx2c4.com ([192.95.5.64]:56633 "EHLO frisell.zx2c4.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937005AbeFRXn4 (ORCPT ); Mon, 18 Jun 2018 19:43:56 -0400 Received: by frisell.zx2c4.com (ZX2C4 Mail Server) with ESMTP id b01b4633; Mon, 18 Jun 2018 23:38:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=zx2c4.com; h=from:to:cc :subject:date:message-id; s=mail; bh=Cky+58ddiHbyISVuNxrQsSSBdRo =; b=1kJhLxuPAnj/uglw+Ol6TR35b0K4NaZOdlRfO/4oPH9hT+54/6et/WGZYOn 69K+QgA7WTJws24OyzVF7+2qYMds+dZyWR3nvqzGc5+449Eny1D9xMrz1VDc28Nb qZ8TlT407JoCF5jJuvknTO9UqWFAdWMPv32ScY1xRoRqNeRL8NO8XNxgSCsL6ZsR PJU3A9NBkkKhW4m78F/35jG8ayJC4cUuHzvuQ01EYyxPN+uAc8IRAvT1F/1No5ML R7XS+0IqnAp4JH3mVKdy7mPt7M3SD0TCv6S1RBN/i0Rtdp+6Cd+oU0I+TtTJ6ecc Gb6KeGKEdqLMJn5XknCoCNIUNMQ== Received: by frisell.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 12b75323 (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256:NO); Mon, 18 Jun 2018 23:38:07 +0000 (UTC) From: "Jason A. Donenfeld" To: tytso@mit.edu, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org Cc: "Jason A. Donenfeld" Subject: [PATCH] random: make crng state queryable Date: Tue, 19 Jun 2018 01:43:47 +0200 Message-Id: <20180618234347.13282-1-Jason@zx2c4.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It is extremely useful to be able to know whether or not get_random_ bytes_wait / wait_for_random_bytes is going to block or not, or whether plain get_random_bytes is going to return good randomness or bad randomness. My particular use case is mitigating certain attacks in WireGuard. A handshake packet arrives and is queued up. Elsewhere a worker thread takes items from the queue and processes them. In replying to these items, it needs to use some random data, and it has to be good random data. If we simply block until we can have good randomness, then it's possible for an attacker to fill the queue up with packets waiting to be processed. Upon realizing the queue is full, WireGuard will detect that it's under a denial of service attack, and behave accordingly. A better approach is just to drop incoming handshake packets if the crng is not yet initialized. Currently the below awful code is necessary to do such a thing. This patch, therefore, makes that information directly accessible. ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ The wrong way to do things: struct rng_is_initialized_callback { struct random_ready_callback cb; atomic_t *rng_state; }; static void rng_is_initialized_callback(struct random_ready_callback *cb) { struct rng_is_initialized_callback *rdy = container_of(cb, struct rng_is_initialized_callback, cb); atomic_set(rdy->rng_state, 2); kfree(rdy); } static bool rng_is_initialized(void) { static atomic_t rng_state = ATOMIC_INIT(0); if (atomic_read(&rng_state) == 2) return true; if (atomic_cmpxchg(&rng_state, 0, 1) == 0) { int ret; struct rng_is_initialized_callback *rdy = kmalloc(sizeof(*rdy), GFP_ATOMIC); if (!rdy) { atomic_set(&rng_state, 0); return false; } rdy->cb.owner = THIS_MODULE; rdy->cb.func = rng_is_initialized_callback; rdy->rng_state = &rng_state; ret = add_random_ready_callback(&rdy->cb); if (ret) kfree(rdy); if (ret == -EALREADY) { atomic_set(&rng_state, 2); return true; } else if (ret) atomic_set(&rng_state, 0); return false; } return false; } Signed-off-by: Jason A. Donenfeld --- drivers/char/random.c | 15 +++++++++++++++ include/linux/random.h | 1 + 2 files changed, 16 insertions(+) -- 2.17.1 diff --git a/drivers/char/random.c b/drivers/char/random.c index a8fb0020ba5c..871724f7b810 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1657,6 +1657,21 @@ int wait_for_random_bytes(void) } EXPORT_SYMBOL(wait_for_random_bytes); +/* + * Returns whether or not the urandom pool has been seeded and thus guaranteed + * to supply cryptographically secure random numbers. This applies to: the + * /dev/urandom device, the get_random_bytes function, and the get_random_{u32, + * ,u64,int,long} family of functions. + * + * Returns: true if the urandom pool has been seeded. + * false if the urandom pool has not been seeded. + */ +bool rng_is_initialized(void) +{ + return crng_ready(); +} +EXPORT_SYMBOL(rng_is_initialized); + /* * Add a callback function that will be invoked when the nonblocking * pool is initialised. diff --git a/include/linux/random.h b/include/linux/random.h index 2ddf13b4281e..c8208e0ff227 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -36,6 +36,7 @@ extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy; extern void get_random_bytes(void *buf, int nbytes); extern int wait_for_random_bytes(void); +extern bool rng_is_initialized(void); extern int add_random_ready_callback(struct random_ready_callback *rdy); extern void del_random_ready_callback(struct random_ready_callback *rdy); extern void get_random_bytes_arch(void *buf, int nbytes);