From: Vlad-Andrei BĂDOIU (78692) <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
ChaCha20 is a cryptographically secure pseudorandom number generator. We replace
the existing implementation, which is not secure, with ChaCha20. The
implementation is based on the reference implementation of the author[1].
[1]
http://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c
Signed-off-by: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
---
lib/ukswrand/Config.uk | 7 +-
lib/ukswrand/Makefile.uk | 1 +
lib/ukswrand/chacha.c | 160 +++++++++++++++++++++++++++++++++++++++
lib/ukswrand/swrand.c | 7 +-
4 files changed, 173 insertions(+), 2 deletions(-)
create mode 100644 lib/ukswrand/chacha.c
diff --git a/lib/ukswrand/Config.uk b/lib/ukswrand/Config.uk
index e056b4c5..199fa62b 100644
--- a/lib/ukswrand/Config.uk
+++ b/lib/ukswrand/Config.uk
@@ -6,12 +6,17 @@ menuconfig LIBUKSWRAND
if LIBUKSWRAND
choice
prompt "Algorithm"
- default LIBUKSWRAND_MWC
+ default LIBUKSWRAND_CHACHA
config LIBUKSWRAND_MWC
bool "Multiply-with-carry"
help
Use multiply-with-carry algorithm
+
+config LIBUKSWRAND_CHACHA
+ bool "ChaCha20"
+ help
+ Use ChaCha20 algorithm
endchoice
choice
diff --git a/lib/ukswrand/Makefile.uk b/lib/ukswrand/Makefile.uk
index da85d381..fe6a63e1 100644
--- a/lib/ukswrand/Makefile.uk
+++ b/lib/ukswrand/Makefile.uk
@@ -4,6 +4,7 @@ CINCLUDES-$(CONFIG_LIBUKSWRAND) += -I$(LIBUKSWRAND_BASE)/include
CXXINCLUDES-$(CONFIG_LIBUKSWRAND) += -I$(LIBUKSWRAND_BASE)/include
LIBUKSWRAND_SRCS-$(CONFIG_LIBUKSWRAND_MWC) += $(LIBUKSWRAND_BASE)/mwc.c
+LIBUKSWRAND_SRCS-$(CONFIG_LIBUKSWRAND_CHACHA) += $(LIBUKSWRAND_BASE)/chacha.c
LIBUKSWRAND_SRCS-$(CONFIG_LIBUKSWRAND_DEVFS) += $(LIBUKSWRAND_BASE)/dev.c
LIBUKSWRAND_SRCS-y += $(LIBUKSWRAND_BASE)/swrand.c
LIBUKSWRAND_SRCS-y += $(LIBUKSWRAND_BASE)/getrandom.c
diff --git a/lib/ukswrand/chacha.c b/lib/ukswrand/chacha.c
new file mode 100644
index 00000000..0ce1b992
--- /dev/null
+++ b/lib/ukswrand/chacha.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
+ *
+ * Copyright (c) 2019, University Politehnica of Bucharest. All rights
reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#include <string.h>
+#include <uk/swrand.h>
+#include <uk/print.h>
+#include <uk/assert.h>
+#include <uk/ctors.h>
+
+struct uk_swrand {
+ int k;
+ __u32 input[16], output[16];
+};
+
+struct uk_swrand uk_swrand_def;
+
+/* This value isn't important, as long as it's sufficiently asymmetric */
+static const char sigma[16] = "expand 32-byte k";
+
+static inline __u32 _uk_rotl32(__u32 v, int c)
+{
+ return (v << c) | (v >> (32 - c));
+}
+
+static inline void _uk_quarterround(__u32 x[16], int a, int b, int c, int d)
+{
+ x[a] = x[a] + x[b];
+ x[d] = _uk_rotl32(x[d] ^ x[a], 16);
+
+ x[c] = x[c] + x[d];
+ x[b] = _uk_rotl32(x[b] ^ x[c], 12);
+
+ x[a] = x[a] + x[b];
+ x[d] = _uk_rotl32(x[d] ^ x[a], 8);
+
+ x[c] = x[c] + x[d];
+ x[b] = _uk_rotl32(x[b] ^ x[c], 7);
+}
+
+static inline void
+_uk_salsa20_wordtobyte(__u32 output[16], const __u32 input[16])
+{
+ __u32 i;
+
+ for (i = 0; i < 16; i++)
+ output[i] = input[i];
+
+ for (i = 8; i > 0; i -= 2) {
+ _uk_quarterround(output, 0, 4, 8, 12);
+ _uk_quarterround(output, 1, 5, 9, 13);
+ _uk_quarterround(output, 2, 6, 10, 14);
+ _uk_quarterround(output, 3, 7, 11, 15);
+ _uk_quarterround(output, 0, 5, 10, 15);
+ _uk_quarterround(output, 1, 6, 11, 12);
+ _uk_quarterround(output, 2, 7, 8, 13);
+ _uk_quarterround(output, 3, 4, 9, 14);
+ }
+
+ for (i = 0; i < 16; i++)
+ output[i] += input[i];
+}
+
+static inline void _uk_key_setup(struct uk_swrand *r, __u32 k[8])
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ r->input[i + 4] = k[i];
+
+ for (i = 0; i < 4; i++)
+ r->input[i] = ((__u32 *)sigma)[i];
+}
+
+static inline void _uk_iv_setup(struct uk_swrand *r, __u32 iv[2])
+{
+ r->input[12] = 0;
+ r->input[13] = 0;
+ r->input[14] = iv[0];
+ r->input[15] = iv[1];
+}
+
+static inline __u32 _infvec_val(unsigned int c, const __u32 v[],
+ unsigned int pos)
+{
+ if (c == 0)
+ return 0x0;
+ return v[pos % c];
+}
+
+void uk_swrand_init_r(struct uk_swrand *r, unsigned int seedc,
+ const __u32 seedv[])
+{
+ __u32 i;
+
+ UK_ASSERT(r);
+ /* Initialize chacha */
+ __u32 k[8], iv[2];
+
+ for (i = 0; i < 8; i++)
+ k[i] = _infvec_val(10, seedv, i);
+
+ iv[0] = _infvec_val(seedc, seedv, i);
+ iv[1] = _infvec_val(seedc, seedv, i + 1);
+
+ _uk_key_setup(r, k);
+ _uk_iv_setup(r, iv);
+
+ r->k = 16;
+}
+
+__u32 uk_swrand_randr_r(struct uk_swrand *r)
+{
+ __u32 res;
+
+ for (;;) {
+ _uk_salsa20_wordtobyte(r->output, r->input);
+ r->input[12] = r->input[12] + 1;
+ if (r->input[12] == 0)
+ r->input[13]++;
+
+ if (r->k < 16) {
+ res = r->output[r->k];
+ r->k += 1;
+ return res;
+ }
+
+ r->k = 0;
+ }
+}
diff --git a/lib/ukswrand/swrand.c b/lib/ukswrand/swrand.c
index b3f410fb..ca267bf0 100644
--- a/lib/ukswrand/swrand.c
+++ b/lib/ukswrand/swrand.c
@@ -80,13 +80,18 @@ ssize_t uk_swrand_fill_buffer(void *buf, size_t buflen)
static void _uk_swrand_ctor(void)
{
unsigned int i;
+#ifdef CONFIG_LIBUKSWRAND_CHACHA
+ unsigned int seedc = 10;
+ __u32 seedv[10];
+#else
unsigned int seedc = 2;
__u32 seedv[2];
+#endif
+ uk_pr_info("Initialize random number generator...\n");
for (i = 0; i < seedc; i++)
seedv[i] = uk_swrandr_gen_seed32();
- uk_pr_info("Initialize random number generator...\n");
uk_swrand_init_r(&uk_swrand_def, seedc, seedv);
}