[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [UNIKRAFT PATCH 1/2] lib/ukswrand: Replace LCR with ChaCha20



Hey,

can't we keep MWC together with ChaCha and compile one of them according the the configuration? It is fine if you mark MWC in the menu as insecure and take ChaCha as default. I could imagine that MWC is faster - is this true?

Thanks,

Simon

On 15.10.19 13:57, Vlad-Andrei BĂDOIU (78692) wrote:
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].

We add a new config option, LIBUKSWRAND_PERFORMANCE to disable the use of
rdrand for seed generation. Currently, the seed is generated randomly only on 
X64.

[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           | 15 ++++--
  lib/ukswrand/Makefile.uk         |  2 +-
  lib/ukswrand/include/uk/swrand.h | 91 ++++++++++++++++++++++++++++++--
  lib/ukswrand/mwc.c               | 54 +++++++++----------
  4 files changed, 124 insertions(+), 38 deletions(-)

diff --git a/lib/ukswrand/Config.uk b/lib/ukswrand/Config.uk
index c58371bb..e4ed6521 100644
--- a/lib/ukswrand/Config.uk
+++ b/lib/ukswrand/Config.uk
@@ -6,18 +6,25 @@ menuconfig LIBUKSWRAND
  if LIBUKSWRAND
  choice
        prompt "Algorithm"
-       default LIBUKSWRAND_MWC
+       default LIBUKSWRAND_CHACHA
-config LIBUKSWRAND_MWC
-       bool "Multiply-with-carry"
+config LIBUKSWRAND_CHACHA
+       bool "ChaCha20"
        help
-               Use multiply-with-carry algorithm
+               Use ChaCha20 algorithm
  endchoice
config LIBUKSWRAND_INITIALSEED
        int "Initial random seed"
        default 23
+config LIBUKSWRAND_PERFORMANCE
+       bool "Performance settings over security"
+       default y
+       help
+               Use LIBUKSWRAND_INITIALSEED for the initial seed, the PRG is no
+               longer cryptographically secure
+
  config LIBUKSWRAND_DEVFS
        bool "Register random and urandom device to devfs"
        select LIBDEVFS
diff --git a/lib/ukswrand/Makefile.uk b/lib/ukswrand/Makefile.uk
index 6cf1223e..b890c818 100644
--- a/lib/ukswrand/Makefile.uk
+++ b/lib/ukswrand/Makefile.uk
@@ -3,6 +3,6 @@ $(eval $(call addlib_s,libukswrand,$(CONFIG_LIBUKSWRAND)))
  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)/mwc.c
  LIBUKSWRAND_SRCS-$(CONFIG_LIBUKSWRAND_DEVFS) += $(LIBUKSWRAND_BASE)/dev.c
  LIBUKSWRAND_SRCS-y += $(LIBUKSWRAND_BASE)/getrandom.c
diff --git a/lib/ukswrand/include/uk/swrand.h b/lib/ukswrand/include/uk/swrand.h
index 8523e207..3b6545dc 100644
--- a/lib/ukswrand/include/uk/swrand.h
+++ b/lib/ukswrand/include/uk/swrand.h
@@ -45,18 +45,99 @@ extern "C" {
  #endif
struct uk_swrand {
-#ifdef CONFIG_LIBUKSWRAND_MWC
-        __u32 Q[4096];
-        __u32 c;
-        __u32 i;
+#ifdef CONFIG_LIBUKSWRAND_CHACHA
+       int k;
+       __u32 input[16], output[16];
  #endif
  };
extern struct uk_swrand uk_swrand_def; -void uk_swrand_init_r(struct uk_swrand *r, __u32 seed);
+/* This value isn't important, as long as it's sufficiently asymmetric */
+static const char sigma[16] = "expand 32-byte k";
+
+void uk_swrand_init_r(struct uk_swrand *r);
  __u32 uk_swrand_randr_r(struct uk_swrand *r);
+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 _get_random_seed(void)
+{
+       __u32 val;
+
+#ifdef CONFIG_LIBUKSWRAND_PERFORMANCE
+       return CONFIG_LIBUKSWRAND_INITIALSEED;
+#endif
+
+#ifdef CONFIG_ARCH_X86_64
+       asm volatile ("rdrand %%eax;"
+               : "=a" (val));
+#else
+       /* TODO: Generate the seed randomly on ARM */
+       val = CONFIG_LIBUKSWRAND_INITIALSEED;
+#endif
+       return val;
+}
  /* Uses the pre-initialized default generator  */
  /* TODO: Add assertion when we can test if we are in interrupt context */
  /* TODO: Revisit with multi-CPU support */
diff --git a/lib/ukswrand/mwc.c b/lib/ukswrand/mwc.c
index 85abf0c6..21c91f3a 100644
--- a/lib/ukswrand/mwc.c
+++ b/lib/ukswrand/mwc.c
@@ -39,8 +39,6 @@
  #include <uk/assert.h>
  #include <uk/ctors.h>
-/* https://stackoverflow.com/questions/9492581/c-random-number-generation-pure-c-code-no-libraries-or-functions */
-#define PHI 0x9e3779b9
  #define UK_SWRAND_CTOR_PRIO    1
struct uk_swrand uk_swrand_def;
@@ -50,45 +48,45 @@ struct uk_swrand uk_swrand_def;
   */
  static void _uk_swrand_ctor(void);
-void uk_swrand_init_r(struct uk_swrand *r, __u32 seed)
+void uk_swrand_init_r(struct uk_swrand *r)
  {
        __u32 i;
UK_ASSERT(r);
+       /* Initialize chacha */
+       // TODO: add config option to enable/disable this
+       __u32 k[8], iv[2];
- r->Q[0] = seed;
-       r->Q[1] = seed + PHI;
-       r->Q[2] = seed + PHI + PHI;
-       for (i = 3; i < 4096; i++)
-               r->Q[i] = r->Q[i - 3] ^ r->Q[i - 2] ^ PHI ^ i;
+       for (i = 0; i < 8; i++)
+               k[i] = _get_random_seed();
- r->c = 362436;
-       r->i = 4095;
+       iv[0] = _get_random_seed();
+       iv[1] = _get_random_seed();
+
+       _uk_key_setup(r, k);
+       _uk_iv_setup(r, iv);
+
+       r->k = 16;
  }
__u32 uk_swrand_randr_r(struct uk_swrand *r)
  {
-       __u64 t, a = 18782LL;
-       __u32 x, y = 0xfffffffe;
-       __u32 i, c;
+       __u32 res;
- UK_ASSERT(r);
+       for (;;) {
+               _uk_salsa20_wordtobyte(r->output, r->input);
+               r->input[12] = r->input[12] + 1;
+               if (r->input[12] == 0)
+                       r->input[13]++;
- i = r->i;
-       c = r->c;
+               if (r->k < 16) {
+                       res = r->output[r->k];
+                       r->k += 1;
+                       return res;
+               }
- i = (i + 1) & 4095;
-       t = a * r->Q[i] + c;
-       c = (t >> 32);
-       x = t + c;
-       if (x < c) {
-               x++;
-               c++;
+               r->k = 0;
        }
-
-       r->i = i;
-       r->c = c;
-       return (r->Q[i] = y - x);
  }
ssize_t uk_swrand_fill_buffer(void *buf, size_t buflen)

If you keep mwc.c and add chacha.c, you may want to move some functions (like this one) to a generic place.

@@ -114,7 +112,7 @@ ssize_t uk_swrand_fill_buffer(void *buf, size_t buflen)
  static void _uk_swrand_ctor(void)
  {
        uk_pr_info("Initialize random number generator...\n");
-       uk_swrand_init_r(&uk_swrand_def, CONFIG_LIBUKSWRAND_INITIALSEED);
+       uk_swrand_init_r(&uk_swrand_def);
  }
UK_CTOR_FUNC(UK_SWRAND_CTOR_PRIO, _uk_swrand_ctor);


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.