From patchwork Mon Jul 20 10:53:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Filardo X-Patchwork-Id: 1332187 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1231::1; helo=merlin.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=merlin.20170209 header.b=rYAnrV4X; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=rjPEQLnX; dkim-atps=neutral Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B9JXS2FH5z9sRf for ; Mon, 20 Jul 2020 20:55:04 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=n3sbxd4QCTWUrV/gavhk49byvXV878B9c22iWD4tPzw=; b=rYAnrV4X5jMDN4mWeY5ceBEXt j8oOdxTTi3keZUdhFWnIp3j6EN/RkSJyTkBabKYYEbAPaSwMQBWUA77jLPsDpbWdoH1NL3i2CPV1V 0xxqAERODX0/mThYkAsre+sPs4Y56ocK32THZJb5nwzVkhb9eRv7lVJumRQc21k7BnatR596R8yoZ /J0UShzEpnhSlqilKsjJJSauUpLo07c10/lAyQ8qCP3qLv1+hOfjWnZbquXHQnI5692Et6nweG1Nq pZqFXMbBueAwUt9/yKW8beNCg7G3WhC564ZUqD9cOgERlEudb7DlhOmYUsSQlyK+POvVEPhBKyHws 4DFXwRk2A==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jxTQ4-000407-CK; Mon, 20 Jul 2020 10:53:16 +0000 Received: from mail-wm1-x341.google.com ([2a00:1450:4864:20::341]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jxTQ0-0003yf-LB for openwrt-devel@lists.openwrt.org; Mon, 20 Jul 2020 10:53:13 +0000 Received: by mail-wm1-x341.google.com with SMTP id q15so21813939wmj.2 for ; Mon, 20 Jul 2020 03:53:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=14jWTA6XzJd7LXu9oVl2nrMkl3XS3YV2X2LL6Gf9Dmg=; b=rjPEQLnXnGylUZfO0mkRGkbHwTZb/Da8ODScHxNQ2ZWo6pFiOSbdWDmKCyUiItA3MQ p8zjYIj3OUumEhuH+Fn1DnINoCl0M7JbbTYbMIDKSi0faDr/3oBXEnc8wRxt47kMvLNM vtf079FCrNXfV6rf/ecHb1bJ7HAAY4xS2bWKEgCFUn27PWtoYqP0kiNAYqh2+XB/gK4V 5Xijkj3wOPa8KoIPkEU7qgJvgLrq7HoOaCTZ+s9cbSzPEAsF2IOk+7DAZX+P0dqVQV7t 1R7eNSQWjDNIYHgmRB2V5/6KlvQhHnChgKIRpyMo9XZ0hCGt7/vLhyz3L9idN/HgbqRX UnVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=14jWTA6XzJd7LXu9oVl2nrMkl3XS3YV2X2LL6Gf9Dmg=; b=Z/bc65UFRocbBE9LPMDaZK1r4aIy0gooHtNcZDi5ZnclyvmBvOwm2k90lRpFHEaXuk 0/0IkwZCHxezn56p6SGLDCB123ATf+p3kF20MDDOCAafYutLSkJJd8aHeAhxfq58pqTX 6Uo+FbtxuFAuJt66wMC1mTcnwKSfk3gyeSYmnOoHIpRmh9V3VEcIulOrc/rfm1I3Hmkp 4aljiFUPH49mFK5DKKHMxauRbMhnw/FQPPszChSC/i69hAefpNJjkpt3PvfcwmFtsIzn BS3V17G0SRiqj/PA9rfiX63CT2/QUX0NINqlVM6RH34VmaXoOgAms8VKlKDrr8Ixrm8S imHg== X-Gm-Message-State: AOAM532lxu+HbF3dGCo4Cl8SCTuTSI1mhgP5LmU/eoSY8POuUTFpSUSK xsyUZzULOpy+iP31jhUkzpVEv7xlUUw= X-Google-Smtp-Source: ABdhPJyQStIb9VpGL+zm+I27Tdf/LfEdGyYY28N68rMmDSSW3R+DZHYFS+HzfLXDdzuh9c++hMAmsQ== X-Received: by 2002:a1c:5982:: with SMTP id n124mr21240497wmb.77.1595242391576; Mon, 20 Jul 2020 03:53:11 -0700 (PDT) Received: from pf.fritz.box ([2a02:8010:63ca:0:ad41:fb8f:65c1:1e24]) by smtp.gmail.com with ESMTPSA id x18sm32079991wrq.13.2020.07.20.03.53.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Jul 2020 03:53:11 -0700 (PDT) From: nwfilardo@gmail.com To: openwrt-devel@lists.openwrt.org Subject: [PATCH v2 3/4] urngd: Add support for read()ing entropy Date: Mon, 20 Jul 2020 11:53:03 +0100 Message-Id: <20200720105304.1090741-3-nwfilardo@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200712205739.238197-1-nwfilardo@gmail.com> References: <20200712205739.238197-1-nwfilardo@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200720_065312_728418_E8B0DC5D X-CRM114-Status: GOOD ( 15.82 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:341 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [nwfilardo[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Nathaniel Wesley Filardo , =?utf-8?q?Petr_=C5=A0tet?= =?utf-8?q?iar?= Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org From: Nathaniel Wesley Filardo This allows us to attach a hwrng, for example. At most one sample will be taken every time we also add entropy via the jitter mechanism. We won't try reading if the stream hasn't indicated its readiness, and we'll go back to waiting if ever the stream produces 0 bytes or an error on read. If the read was successful, we will optimistically assume it will be next time, too, avoiding the need to asynchronously wait for sample availability most of the time. Signed-off-by: Nathaniel Wesley Filardo --- urngd.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/urngd.c b/urngd.c index 31181f0..1168674 100644 --- a/urngd.c +++ b/urngd.c @@ -61,6 +61,7 @@ unsigned int debug; struct urngd { struct uloop_fd rnd_fd; + struct uloop_fd file_fd; struct rand_data *ec; }; @@ -72,6 +73,11 @@ static inline void memset_secure(void *s, int c, size_t n) __asm__ __volatile__("" : : "r" (s) : "memory"); } +static inline bool entropy_file_available(struct urngd *u) +{ + return (u->file_fd.fd >= 0) && !(u->file_fd.registered); +} + static size_t write_entropy(struct urngd *u, struct rand_pool_info *rpi) { int ret; @@ -88,7 +94,7 @@ static size_t write_entropy(struct urngd *u, struct rand_pool_info *rpi) return ret; } -static size_t gather_entropy(struct urngd *u) +static size_t gather_jitter_entropy(struct urngd *u) { ssize_t ent; size_t ret = 0; @@ -110,12 +116,43 @@ static size_t gather_entropy(struct urngd *u) return ret; } +static size_t gather_file_entropy(struct urngd *u) { + static const size_t file_bytes = 1024; + struct rand_pool_info *rpi = alloca(sizeof(*rpi) + file_bytes); + ssize_t ent; + size_t ret; + + ent = read(u->file_fd.fd, (char *)&rpi->buf[0], file_bytes); + if (ent > 0) { + rpi->buf_size = ent; + rpi->entropy_count = 8 * ent; + ret = write_entropy(u, rpi, "file"); + + memset_secure(&rpi->buf, 0, ent); + } else { + if ((ent < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK)) + LOG("read(file) error %s\n", strerror(errno)); + ret = 0; + + uloop_fd_add(&u->file_fd, ULOOP_READ); + } + + return ret; +} + static void low_entropy_cb(struct uloop_fd *ufd, unsigned int events) { struct urngd *u = container_of(ufd, struct urngd, rnd_fd); DEBUG(2, DEV_RANDOM " signals low entropy\n"); - gather_entropy(u); + gather_jitter_entropy(u); + if (entropy_file_available(u)) + gather_file_entropy(u); +} + +static void file_ready_cb(struct uloop_fd *ufd, unsigned int events) +{ + uloop_fd_delete(ufd); } static void urngd_done(struct urngd *u) @@ -129,6 +166,11 @@ static void urngd_done(struct urngd *u) close(u->rnd_fd.fd); u->rnd_fd.fd = 0; } + + if (u->file_fd.fd >= 0) { + close(u->file_fd.fd); + u->file_fd.fd = -1; + } } static bool urngd_init(struct urngd *u) @@ -154,6 +196,18 @@ static bool urngd_init(struct urngd *u) uloop_fd_add(&u->rnd_fd, ULOOP_WRITE); + if (u->file_fd.fd >= 0) { + int ret; + + u->file_fd.cb = file_ready_cb; + ret = uloop_fd_add(&u->file_fd, ULOOP_READ); + if (ret == -1 && errno == EPERM) { + LOG("File (-f) does not support polling;" + " assuming that's OK.\n"); + u->file_fd.registered = false; + } + } + return true; } @@ -164,11 +218,24 @@ static int usage(const char *prog) #ifdef URNGD_DEBUG " -d Enable debug messages\n" #endif + " -f Source entropy from \n" " -S Print messages to stdout\n" "\n", prog); return 1; } +static void do_opt_file(struct urngd *u, const char *filename) +{ + if (u->file_fd.fd >= 0) { + close(u->file_fd.fd); + } + + u->file_fd.fd = open(filename, O_RDONLY | O_NONBLOCK); + if (u->file_fd.fd < 0) { + ERROR("%s open failed: %s\n", filename, strerror(errno)); + } +} + int main(int argc, char **argv) { int ch; @@ -182,13 +249,18 @@ int main(int argc, char **argv) } #endif - while ((ch = getopt(argc, argv, "d:S")) != -1) { + urngd_service.file_fd.fd = -1; + + while ((ch = getopt(argc, argv, "d:f:S")) != -1) { switch (ch) { #ifdef URNGD_DEBUG case 'd': debug = atoi(optarg); break; #endif + case 'f': + do_opt_file(&urngd_service, optarg); + break; case 'S': ulog_channels = ULOG_STDIO; break; @@ -207,7 +279,7 @@ int main(int argc, char **argv) LOG("v%s started.\n", URNGD_VERSION); - gather_entropy(&urngd_service); + gather_jitter_entropy(&urngd_service); uloop_run(); uloop_done();