Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp773868ybb; Sat, 28 Mar 2020 09:44:33 -0700 (PDT) X-Google-Smtp-Source: ADFU+vsSQmCEVeR+0hE6RZ2p5/Kry+jH5o+437mi+BnqKeRAG7YYn1x5M9DHjo36fOrMPmy8/nvk X-Received: by 2002:a05:6830:4038:: with SMTP id i24mr3420891ots.0.1585413873400; Sat, 28 Mar 2020 09:44:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585413873; cv=none; d=google.com; s=arc-20160816; b=BqhDj+Ev69xgxpJUl9+7CTjeri+kfYC+quOWBytGP53MkmISg8SiUAUD6h9rCdaVCv QEPqs/WeG4rNjvu5Th3v/jIbM8LepqZcN5aXTYzGq65uCu5egjrZZoJclloQE0ZcJFQD PokPgDK1To0A/esfeiqW69j0AD61T8AWGAneqtxCNQU1pUUkWEn8RCrVS7W1AVBEDKR/ 99b0Qeehdbl8ETgoTqmPmyGp28d2pCCfOiKCAjGp1KAe6cFb5dAShA+G6Z7kEi1kmd1A 3pUYZ6HEmxG51fc4Nng4JbrH9Sr1IGhlD3Zp+qbcdMJyWFp5TFs5Ca0E3ZCwfnFnkMaj oJuw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:date:from:message-id; bh=d1FbIhtdTsTdMJB9OHfhbMxb28OCEz0qX+lytHYv4DM=; b=iXrUwGCE8htN9DWqFpwd0tDsm+GJz0mzGdxzvn1AK/I0ndpvVtnmTgTF1gkDMZso8L UtAXH1N7NCxhq3h/JXX93lJODBb08PjChrNOWVHuyAVBUStq+/6itcU/kIDXXhVtp6Ql v6XzTWVLFXLmU8Sug+dmAyBlcsopz9NY3DTH7Lgeyp5gZHYTe9s4fPuefJQ8NbBUQkua KHW9b8ENsKXJfwSfXOb0rVgw3F+ExQkisCeN+7cydUUjbdUyC1FXpPC0rCDMi3zIQVkG jdI+8WcJvNbKrV+SGWJeXjI+p2Kdl0ce1tT3vRRu/055UAyKGFBQTfI09iI9sOpjepBp 29kw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l18si3626096oig.223.2020.03.28.09.44.20; Sat, 28 Mar 2020 09:44:33 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727834AbgC1Qnp (ORCPT + 99 others); Sat, 28 Mar 2020 12:43:45 -0400 Received: from mx.sdf.org ([205.166.94.20]:50046 "EHLO mx.sdf.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727706AbgC1Qn3 (ORCPT ); Sat, 28 Mar 2020 12:43:29 -0400 Received: from sdf.org (IDENT:lkml@sdf.lonestar.org [205.166.94.16]) by mx.sdf.org (8.15.2/8.14.5) with ESMTPS id 02SGhQWq022097 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits) verified NO); Sat, 28 Mar 2020 16:43:27 GMT Received: (from lkml@localhost) by sdf.org (8.15.2/8.12.8/Submit) id 02SGhQQ5025294; Sat, 28 Mar 2020 16:43:26 GMT Message-Id: <202003281643.02SGhQQ5025294@sdf.org> From: George Spelvin Date: Fri, 20 Mar 2020 19:38:09 -0400 Subject: [RFC PATCH v1 50/50] random: add get_random_nonce() To: linux-kernel@vger.kernel.org, lkml@sdf.org Cc: "Theodore Ts'o" , "Jason A. Donenfeld" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is like get_random_bytes(), but uses the same batched entropy buffer as get_random_u32(). Many kernel users of get_random_bytes could be switched to this. E.g. eth_random_addr(). But before doing that, we should decide if it wouldn't be better to rename this function to get_random_bytes, and let the smaller number of sites which really need strongly secure random numbers use a different name like "get_secret_bytes()". Code size +731 bytes (x86-64) Signed-off-by: George Spelvin Cc: Theodore Ts'o Cc: Jason A. Donenfeld --- drivers/char/random.c | 77 ++++++++++++++++++++++++++++++++++++++++++ include/linux/random.h | 1 + 2 files changed, 78 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index 67bdfb51eb25c..02e80000310ce 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -342,6 +342,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -2569,6 +2570,82 @@ u32 get_random_u32(void) } EXPORT_SYMBOL(get_random_u32); +/** + * get_random_nonce - Generate a random string of bytes + * @buf: The buffer to fill + * @nbytes: The size of the buffer + * + * This generates cryptographically strong bytes, at less cost than + * get_random_bytes. In particular, anti-backtracking is not + * provided. It is suitable for public values (random cookies or + * MAC addresses which are supposed to be unguessable), and for + * secret values which are stored in the kernel as long as they + * are valuable, such as SipHash keys or stack canaries. + * + * In general, if the calling code does not use memzero_explicit(), it + * is safe to use this function rather than get_random_bytes. + * + * TODO: Perhaps get_random_bytes should be renamed to get_secret_bytes + * and this function should be renamed to get_random_bytes? + */ +void get_random_nonce(void *buf, size_t nbytes) +{ + unsigned long ret; + size_t pos; + unsigned long flags; + struct batched_entropy *batch; + static void *previous; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + while (nbytes >= sizeof(ret)) { + if (!arch_get_random_long(buf)) + goto software; + buf += sizeof(ret); + nbytes -= sizeof(ret); + } + if (nbytes) { + if (!arch_get_random_long(&ret)) + goto software; + memcpy(buf, &ret, nbytes); + } + return; +software: +#else + while (arch_get_random_long(&ret)) { + if (nbytes > sizeof(ret)) { + put_unaligned(ret, (unsigned long *)buf); + buf += sizeof(ret); + nbytes -= sizeof(ret); + } else { + memcpy(buf, &ret, nbytes); + return; + } + } +#endif + + warn_unseeded_randomness(&previous); + + local_irq_save(flags); + batch = this_cpu_ptr(&batched_entropy); + pos = batch->position + 1; + if (unlikely(crng_init != batch->crng_init)) { + batch->crng_init = crng_init; + pos = CHACHA_BLOCK_SIZE; + } + + while (nbytes > CHACHA_BLOCK_SIZE - pos) { + memcpy(buf, batch->entropy8 + pos, CHACHA_BLOCK_SIZE - pos); + buf += CHACHA_BLOCK_SIZE - pos; + nbytes -= CHACHA_BLOCK_SIZE - pos; + extract_crng(batch->entropy32); + pos = 0; + } + batch->position = pos + nbytes - 1; + memcpy(buf, batch->entropy8 + pos, nbytes); + local_irq_restore(flags); +} +EXPORT_SYMBOL(get_random_nonce); + /** * __get_random_max32 - Generate a uniform random number 0 <= x < range < 2^32 * @range: Modulus for random number; must not be zero! diff --git a/include/linux/random.h b/include/linux/random.h index 97d3469f3aad8..de9eae20b69af 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -50,6 +50,7 @@ extern const struct file_operations random_fops, urandom_fops; u32 get_random_u32(void); u64 get_random_u64(void); +void get_random_nonce(void *buf, size_t nbytes); static inline unsigned int get_random_int(void) { return get_random_u32(); -- 2.26.0