Giter VIP home page Giter VIP logo

mirage-crypto's Introduction

mirage-crypto - Cryptographic primitives for MirageOS

%%VERSION%%

mirage-crypto is a small cryptographic library that puts emphasis on the applicative style and ease of use. It includes basic ciphers (AES, 3DES, RC4, ChaCha20/Poly1305), AEAD primitives (AES-GCM, AES-CCM, ChaCha20/Poly1305), public-key primitives (RSA, DSA, DH), elliptic curves (NIST P-256, P-384, P-521, and curve 25519), and a strong RNG (Fortuna).

RSA timing attacks are countered by blinding. AES timing attacks are avoided by delegating to AES-NI.

Mirage-crypto is a fork of the ocaml-nocrypto written by David Kaloper. It was forked with the permission of the original author in order to facilitate changes (e.g. build system) required by Mirage that the upstream didn't have time to keep up with.

Mirage-crypto-rng embeds the former mirage-entropy opam package, which implements various entropy sources:

  • non-deterministic execution time (used at initial seeding, see the whirlwind RNG paper)
  • a hook into the Lwt event loop that collects a timestamp of each event
  • rdseed and rdrand (x86/x86-64 only)

API documentation online

Build

dune build
dune runtest

FAQ

RNG seeding

If RNG fails with Fatal error: exception Unseeded_generator, you need to seed it.

Lwt:

let () = Mirage_crypto_rng_lwt.initialize (module Mirage_crypto_rng.Fortuna)

Unix:

let () = Mirage_crypto_rng_unix.initialize (module Mirage_crypto_rng.Fortuna)

mirage-crypto's People

Contributors

avsm avatar chris00 avatar dfaranha avatar dinosaure avatar eduardorfs avatar edwintorok avatar emillon avatar fangyaling avatar firobe avatar glondu avatar haesbaert avatar hannesm avatar jonahbeckford avatar julow avatar marmarek avatar mato avatar misterda avatar mor1 avatar paarthenon avatar pinotree avatar pkhry avatar pqwy avatar psafont avatar reynir avatar samoht avatar samueldurantes avatar seliopou avatar talex5 avatar thelortex avatar yomimono avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mirage-crypto's Issues

getrandom not found on Ubuntu 16.04 (GLIBC 2.23)

I tried to compile mirage-crypto and on my distribution, sys/random.h does not exist - and appears only on >= GLIBC.2.25 (according to changelog).

I did this little patch to be able to compile mirage-crypto on my side:

diff --git a/rng/unix/mc_getrandom_stubs.c b/rng/unix/mc_getrandom_stubs.c
index fc8b741..9a4f849 100644
--- a/rng/unix/mc_getrandom_stubs.c
+++ b/rng/unix/mc_getrandom_stubs.c
@@ -6,9 +6,11 @@
 #include <caml/bigarray.h>
 
 #if defined(__linux)
+# include <errno.h>
 // on Linux, we use getrandom and loop
-#include <sys/random.h>
-#include <errno.h>
+
+# if __GLIBC__ > 2 || __GLIBC_MINOR__ > 24
+# include <sys/random.h>
 
 void raw_getrandom (uint8_t *data, uint32_t len) {
   int r, off = 0;
@@ -19,6 +21,19 @@ void raw_getrandom (uint8_t *data, uint32_t len) {
     off += r;
   }
 }
+#else
+# include <sys/syscall.h>
+
+void raw_getrandom (uint8_t *data, uint32_t len) {
+  int r, off = 0;
+  while (off < len) {
+    r = syscall(SYS_getrandom, data + off, len - off, 0);
+    if (r < 0 && errno == EINTR) continue;
+    else if (r < 0) uerror("getrandom", Nothing);
+    off += r;
+  }
+}
+#endif
 
 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__))
 // on BSD and macOS, loop (in pieces of 256) getentropy

On armv6/7, mc_cycle_counter () fails with SIGILL, Illegal instruction

I recently compiled and ran the following program on an Odroid U2 (ARM Cortex A9 Quad-Core) and also on a Raspberry Pi 1:

let () = Mirage_crypto_rng_unix.initialize ()

The result was a Illegal instruction (core dumped).
The cause seems to be this line

__asm__ __volatile__("mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));

in entropy_cpu_stubs.c.
This tries to access the CNTVCT, Virtual Count register on the ARM CPU, presumably in order to seed the RNG.
However, according to the Documentation for the ARM Architecture, these Generic Timer Registers are not accessible from user space. So this approach doesn't work and will fail on all ARMv7 and up.
To use the Timer Registers, you have to enable access via CNTKCTL from kernel mode, which basically means you have to write a kernel module.

After some searching I found this: https://github.com/thoughtpolice/enable_arm_pmu which uses a similar approach with the ARM's PMU registers, which are subject to the same restrictions as the generic timers. The author also has an interesting Blog Post explaining the matter in detail.

Cheers.

PRNG and entropy on MirageOS

The current state is as follows

  • users of randomness use the Mirage_random.S device, with the function generate : int -> Cstruct.t
  • mirage-entropy collects entropy (whirlwind CPU-level data races for initial seed, rdrand/rdseed/timers for periodic reseeding by registering a callback with Mirage_runtime.enter_hooks (executed every time a step of the main event loop is executed) - each mirag-entropy registered handler gets the same bytes of entropy (4 bytes cycle counter + 8 bytes RDSEED (or RDRAND) if available)
  • the mirage utility emits Nocrypto_entropy_mirage.initialize () if the nocrypto random device is used. There is as well code in mirage to detect whether nocrypto is in the dependency cone of a unikernel, and if so if the initialization code is emitted (to ensure there's no nocrypto RNG that doesn't get entropy).
  • Nocrypto_entropy_mirage registers itself (well, the default generator) as entropy sink
  • another RNG implementation is mirage-random-stdlib, also using mirage-entropy for a seed
  • The mirage utility provides the --prng keyword to select between fortuna (nocrypto) and stdlib RNG

This works mostly fine, but we could simplify it:

  • mirage-crypto-rng does no longer depend on zarith/gmp, thus a strong RNG could be used in every unikernel
  • the duplication of the interface Mirage_random.S and Mirage_crypto_rng.Generator is not necessary, the latter could be deprecated (or just be the former)?
  • I cannot find a use-case for the ability to feed multiple RNGs from mirage-entropy, this could be removed
  • If we have the mutable Mirage_crypto_rng.generator anyways, mirage-entropy could push entropy there (invert the dependencies, mirage-entropy would depend on mirage-crypto-rng)
  • ensure that when the default generator is set, this should invoke the bootstrap/initial seed from mirage-entropy (could be done by mirage-entropy registering a callback in mirage-crypto-rng)
  • I also cannot think of a use-case where the RNG is set during normal unikernel execution (only during startup)

At the end of the day, I propose that the mirage utility should (first) initialize (call connect) the mirage-entropy (registering the bootstrap callback), and then the mirage-crypto-rng connect (which woucl set the default generator to Fortuna (or whatever else was selected by a user). I'm interested in feedback and discussion of this proposal, especially if we go down this road to stick to a initialization protocol that is sensible before a release of mirage-crypto. Thanks for reading.

Bus error in xor_into on arm32

Looks like xor_into assumes its arguments are 8-byte aligned, but this isn't always the case.
I think this is the cause of the capnp-rpc unit-test failures on arm32 in CI (e.g. https://ci.ocamllabs.io:8100/job/2020-08-10/095735-ci-ocluster-build-9830f6).

The error is:

test_lwt alias test-lwt/runtest (got signal BUS)

Here's a gdb stacktrace:

#0  0x012a6dca in xor_into (n=<optimized out>, 
    dst=0x2ec4b58 "\303C\235\243\020\351\317\311\063\350\003w\224\214\006\337\365\237\263r\223\325ytN\ag\211\063\213Ut\207\325R\274\200\210\064\260OK\255\315\377\332\276\212\327\235\350~\265\060\061\023d\006\260\265\301}\251<\033\344P%Kax\r\335l\373Y\356\231\207\020\313\202p~D\340}\030b&X?\002\306\232y\034\222x\220\024\061F\203*\371uQ\277\341\207\356\342\344\263\303\234r\377\252\340\372}a\016\203\241\326\024@\321F\327_i\006yh\215\234\235\026\001\310o\a_\210\257K\262e2Y-\224\326\034\327\237}avRS2\354(\342\245|^oI\344Z\275\200\277]W\203g\323\306\333~\251m\241\341%Au\233\326\303P<m"..., 
    src=0x2ec1ed1 "\310C\237\f\020\351\315b3\352\245G\026\216\244\357w\236\071\322\220\327xvL\017=\372\366\334\365MLLb\261\206\201\036\066\a\315Z\300\376\333\265\217\327\255\370O\273") at native/misc.c:6
#1  mc_xor_into_generic (b1=<optimized out>, off1=<optimized out>, b2=<optimized out>, off2=<optimized out>, n=n@entry=1385)
    at native/misc.c:51
#2  0x012a6fec in mc_xor_into (b1=<optimized out>, off1=<optimized out>, b2=<optimized out>, off2=<optimized out>, n=1385)
    at native/misc_sse.c:36
#3  0x00e105ca in camlMirage_crypto__Cipher_block__encrypt_843 () at src/cipher_block.ml:223
#4  0x00e10eb0 in camlMirage_crypto__Cipher_block__authenticate_decrypt_984 () at src/cipher_block.ml:300
#5  0x00daa7dc in camlTls__Engine__decrypt_inner_2791 () at lib/engine.ml:302
#6  0x00dac00c in camlTls__Engine__fun_3029 () at lib/engine.ml:501
#7  0x00dac7c4 in camlTls__Engine__handle_records_1909 () at lib/engine.ml:542
#8  0x00dac89a in camlTls__Engine__fun_3196 () at lib/engine.ml:544
#9  0x00dac89a in camlTls__Engine__fun_3196 () at lib/engine.ml:544
#10 0x00dac89a in camlTls__Engine__fun_3196 () at lib/engine.ml:544
#11 0x00dac960 in camlTls__Engine__fun_3212 () at lib/engine.ml:551
#12 0x00dac534 in camlTls__Engine__handle_tls_1905 () at lib/engine.ml:549
#13 0x00d62fc6 in camlTls_mirage__fun_1667 () at mirage/tls_mirage.ml:62
#14 0x00d63500 in camlTls_mirage__drain_handshake_753 () at mirage/tls_mirage.ml:130
#15 0x010e2c6c in camlLwt__callback_1288 () at src/core/lwt.ml:1867

Note that src=0x2ec1ed1 is not aligned.

No known cycle-counting instruction on ppc64

mirage-crypto fails to install on ppc64:

#=== ERROR while compiling mirage-crypto.0.8.1 ================================#
# context              2.0.7 | linux/ppc64 | ocaml-base-compiler.4.10.0 | file:///home/opam/opam-repository
# path                 ~/.opam/4.10/.opam-switch/build/mirage-crypto.0.8.1
# command              ~/.opam/4.10/bin/dune build -p mirage-crypto -j 79
# exit-code            1
# env-file             ~/.opam/log/mirage-crypto-8-9e20af.env
# output-file          ~/.opam/log/mirage-crypto-8-9e20af.out
### output ###
#       ocamlc src/entropy_cpu_stubs.o (exit 2)
# (cd _build/default/src && /home/opam/.opam/4.10/bin/ocamlc.opt -g -I /home/opam/.opam/4.10/lib/bigarray-compat -I /home/opam/.opam/4.10/lib/cstruct -I /home/opam/.opam/4.10/lib/eqaf -I /home/opam/.opam/4.10/lib/eqaf/bigstring -I /home/opam/.opam/4.10/lib/eqaf/cstruct -ccopt -O2 -ccopt -fno-strict-aliasing -ccopt -fwrapv -ccopt -fPIC -ccopt --std=c99 -ccopt -Wall -ccopt -Wextra -ccopt -Wpedantic -ccopt -O3 -ccopt -g -o entropy_cpu_stubs.o native/entropy_cpu_stubs.c)
# native/entropy_cpu_stubs.c: In function 'caml_cycle_counter':
# native/entropy_cpu_stubs.c:86:2: error: #error ("No known cycle-counting instruction.")
#  #error ("No known cycle-counting instruction.")
#   ^~~~~
# native/entropy_cpu_stubs.c:88:1: warning: control reaches end of non-void function [-Wreturn-type]

Any suggestions on how to get this working?

Compilation failure with GCC 11.x

The release of GCC 11 introduces a new warning array-parameter causing the build of mirage-crypto's C stubs to fail:

native/des_generic.c:404:31: error: argument 1 of type ‘unsigned char[16]’ with mismatched bound [-Werror=array-parameter=]
  404 | void mc_des2key(unsigned char hexkey[16], short mode) /* stomps on Kn3 too */
      |                 ~~~~~~~~~~~~~~^~~~~~~~~~
In file included from native/des_generic.c:19:
native/des_generic.h:67:24: note: previously declared as ‘unsigned char *’
   67 | extern void mc_des2key(unsigned char *, short);
      |                        ^~~~~~~~~~~~~~~
native/des_generic.c:536:31: error: argument 1 of type ‘unsigned char[24]’ with mismatched bound [-Werror=array-parameter=]
  536 | void mc_des3key(unsigned char hexkey[24], short mode)
      |                 ~~~~~~~~~~~~~~^~~~~~~~~~
In file included from native/des_generic.c:19:
native/des_generic.h:126:24: note: previously declared as ‘unsigned char *’
  126 | extern void mc_des3key(unsigned char *, short);
      |                        ^~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

Initialization takes time

If you make an executable which links with just mirage-crypto-pk, this executable takes a significant time to load (more than 1s on my device).

This is with mirage-crypto-pk version 0.6.1.

Here are some steps to reproduce:

[Thu 17:47:35] (romain@tarteflambee) /tmp/test> ls
dune  main.ml
[Thu 17:48:28] (romain@tarteflambee) /tmp/test> cat dune
(executables
 (names main)
 (libraries mirage-crypto-pk)
 (flags (:standard -linkall)))
[Thu 17:48:30] (romain@tarteflambee) /tmp/test> cat main.ml
let () = print_endline "LOADED"
[Thu 17:48:32] (romain@tarteflambee) /tmp/test> dune build main.exe
Info: Creating file dune-project with this contents:
| (lang dune 2.4)
[Thu 17:48:48] (romain@tarteflambee) /tmp/test> time _build/default/main.exe
LOADED
_build/default/main.exe  1.01s user 0.00s system 99% cpu 1.006 total

ERROR while compiling mirage-crypto.0.6.2

#=== ERROR while compiling mirage-crypto.0.6.2 ================================#
# context     2.0.6 | linux/arm32 | ocaml-base-compiler.4.07.1 | https://opam.ocaml.org#91605213
# path        ~/.opam/4.07.1/.opam-switch/build/mirage-crypto.0.6.2
# command     ~/.opam/opam-init/hooks/sandbox.sh build dune build -p mirage-crypto -j 1
# exit-code   1
# env-file    ~/.opam/log/mirage-crypto-17271-6aa130.env
# output-file ~/.opam/log/mirage-crypto-17271-6aa130.out
### output ###
# native/ghash_generic.c:101:26: error: expected expression before ‘)’ token
# [...]
# native/ghash_generic.c:100:49: warning: unused parameter ‘off’ [-Wunused-parameter]
#  mc_ghash (value m, value hash, value src, value off, value len) {
#                                            ~~~~~~^~~
# native/ghash_generic.c: In function ‘mc_ghash_key_size’:
# native/ghash_generic.c:92:1: warning: control reaches end of non-void function [-Wreturn-type]
#  }
#  ^
# At top level:
# native/ghash_generic.c:23:26: warning: ‘r’ defined but not used [-Wunused-const-variable=]
#  static const __uint128_t r = __set_uint128_t (0xe100000000000000, 0);
#                           ^

EC improve performance

The numbers in #107 (comment) hint that doing arithmetic in OCaml (by calling the C primitives) is not very high-performance (heap allocations for temporary values may have some impact as well).

Namely, check and eventually reimplement in C:

  • Make_point.is_solution_to_curve_equation
  • Make_point.to_affine_raw
  • Make_scalar.scalar_mult
  • Make_dsa.x_of_finite_point_mod_n
  • Make_dsa.sign
  • Make_dsa.verify

Question: Exposing the tag in AES-GCM

I'm encrypting something in Ocaml and decrypting it in PyCryptodome. In PyCryptodome, the tag is explicitly exposed and passed in for verification and in mirage-crypto it's implicit. See the PyCryptodome example here:

https://pycryptodome.readthedocs.io/en/latest/src/examples.html#encrypt-data-with-rsa

What's annoying is that I cannot run the PyCryptodome decryption with verification because I don't have the tag. And when I decrypt it in PyCryptodome I need to explicitly remove the tag by slicing out the last 16 bytes.

Does anyone understand why these interfaces are different? And should the tag be exposed in this interface to work with other libraries?

Improve support on Linux and X (s390x)

From #129 (comment) instead of the expensive STCK, the less expensive STCKF could be used (if it meets our needs, namely being not easy to predict). Additionally, performance measurements should be taken.

PRNG support (atm using rdrand/rdseed on x86) should be improved with the PRNO instruction (see #129 (comment)) on s390x (and potentially on arm & riscv using some special instructions as well).

Also, various platforms have extended hash & cipher support now (x86 has sha2 instructions, arm has multiple of them, s390x has poly1305, ...).

Memory leak in RNG _sources?

According to perf, ocluster-scheduler is spending a lot of time in List.length:

-   57.92%  ocluster-schedu  ocluster-scheduler  [.] camlStdlib__list__length_aux_83
     camlStdlib__list__length_aux_83
     camlMirage_crypto_rng__Entropy__register_source_143
     camlMirage_crypto_rng__Entropy__cpu_rng_596
     camlMirage_crypto_rng_lwt__one_151
     camlLwt__callback_1288
     camlLwt__iter_callback_list_873
     camlLwt__run_in_resolution_loop_926
     camlLwt__resolve_946
     camlLwt__wakeup_general_983
     caml_start_program

I don't really understand this code, but it looks like initialize calls rdrand_task

That then calls Entropy.cpu_rng once per second. Each time, that calls register_source, which gets the length of _sources and then appends to it. As far as I can see, nothing is ever removed from this list.

mitigate timing side-channels in public key cryptography: use powm_sec instead of powm

RSA optionally uses blinding for mitigation, but DH and DSA do not.

Using powm_sec should be done carefully, since it is different from powm:

  • raises an exception if the exponent is negative or zero
  • raises an exception if the modulus is even

there are several ways forward:

  • document exceptions potentially raised
  • validate input before passing it to powm_sec to avoid exceptions
  • surround with try .. catch

other questions

  • are blinding and powm_sec orthogonal? does it make sense to use both? (@hannesm thinks not since both attempt to mitigate the same issue)
    • after more reading, blinding modifies c (in c ^ d mod n) by multiplication and thus prevents timing information of the reduction to leak secret data
    • powm_sec is concerned about the exponent d
  • should powm_sec be used for public data (i.e. verification, c ^ e mod n), @cfcs mentions "c may be private", reference needed

decrypted message has \u0000 left padding

The RSA encryption algorithm adds left padding \u0000 in the decrypted message.Is there any way to remove the padding?

"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000["abc","xyz","pqr"]"

Use ocaml-base64 instead internal implementation

Currently, mirage-crypto uses its own implementation of base64 where the MirageOS organization has an other ocaml-base64 implementation.

For my perspective, we have 3 issues:

  • performance
  • tests
  • distribution of mirage-crypto

Tests

ocaml-base64 has, at the end, more tests than what mirage-crypto provides. It comes with a fuzzer and a great work was already done about implementation.

Performances

ocaml-base64 comes finally from the nocrypto's base64.ml module and we already did some benchmark between an imperative implementation (the old version of ocaml-base64) and a functional implementation. Results are available in mirage/ocaml-base64#24.

However, some changes was done then and mirage-crypto uses Cstruct.t where ocaml-base64 is only able to compute bytes and string. I extended the initial benchmark of ocaml-base64 to include the current version of mirage-crypto and a decode/encode with Cstruct.{of_string,to_string}.

This is my result in my computer: benchmark.

As we can see, the most interesting is Base64 (cstruct) which still (for large inputs) faster than the mirage-crypto implementation. The benchmark is available into mirage/ocaml-base64#41.

Distribution

Of course, the main question is about the distribution of mirage-crypto where we will add a dependency into a external package. For me, anyone who works on mirage-crypto has the ability to, at least, improve ocaml-base64 and submit a pull-request.

I mean, ocaml-base64 is under the control of the MirageOS team and it does not own by someone external or not totally aware about MirageOS. So, I don't see any blockers to use ocaml-base64 here instead.

Conclusion

This issue wants to follow discussion about a possible integration of ocaml-base64, I will prepare a pull request then.

entropy sources registration protocol

at the moment, there's the polyvar Mirage_crypto_rng.Entropy.source, which is rather static, not extensible, and a bit useless. The internal type is an int (for source) used in the accumulator. The function Entropy.add_source dynamically adds sources to a private list to be able to expose (for printing) which entropy sources are active.

Instead of that, a private type source (internally an int) should be used, and a register_source : string -> source function to get values of type source. The accumulator should take such a source. This would be more accurate and less hacky, and extensible (i.e. third-party code can insert their own sources). It is likely only an internal API change since nobody does use these entropy sources externally at the moment.

cleanup CI scripts

They now contain lots of version numbers and package names, which they did not before the 0.10.7 release (namely .cirrus.yml and files in .github/actions). Would be great to reduce the maintenance overhead of the CI scripts again.

Config flags are not correct when used in cross-architecture-compilation with Dune 3

With Dune 2, cross-compiling mirage-crypto from x86 to aarch64 was working fine.

With Dune 3, it fails with the following error:

File "duniverse/mirage-crypto/src/dune", line 9, characters 47-51:
9 |   (names detect_cpu_features misc misc_sse md5 sha1 sha256 sha512 hash_stubs
                                                   ^^^^
aarch64-linux-gnu-gcc: error: unrecognized command-line option ‘-mrdrnd’
aarch64-linux-gnu-gcc: error: unrecognized command-line option ‘-mrdseed’
aarch64-linux-gnu-gcc: error: unrecognized command-line option ‘-mssse3’
aarch64-linux-gnu-gcc: error: unrecognized command-line option ‘-maes’
aarch64-linux-gnu-gcc: error: unrecognized command-line option ‘-mpclmul’

It looks like x86 CPU-specific optimisations are enabled even if we are cross-compiling for arm64. So what happens is that the configurator is configuring for the host instead of the target.

instead of compile-time cpu feature detection (of AESNI etc.), do load-time (run-time) feature detection

this is useful for both reproducible builds and general deployment. at the moment, it can be forced via the MIRAGE_CRYPTO_ACCELERATE environment variable, but this is tedious. It is crucial to preserve the performance characteristics (i.e. do not check CPU capabilities each time AES is used). Similar code is already present in the entropy stubs, which at load time figure out whether RDRAND/RDSEED are supported.

Uncommon.Cs.ct_find_uint8 is not constant-time

The code currently looks like this (I've inserted comments):

  let ct_find_uint8
    ?(off=0)  (* branch on value of [off: int option] *)
    ~f cs =
    let rec go acc i = function
      | 0 -> acc
      | n ->
          let acc = match (acc, f (get_uint8 cs i))
           with 
(* [match] introduces a branch; since we branch on a sensitive value this
means we leak timing of whether or not [f] is true.
Example: If we always take one branch, the branch predictor will be
  hot for our code.
If we find something in the middle, we disrupt that.
Depending on at what offset we find a match, we may or may not prime
 the branch predictor again. That's worse than just leaking the predicate,
since it can leak the index of the the matching predicate.

             *)
            | (None, true) ->

              Some i (* allocating a new Some box is observable,
                     so we leak the information that predicate [f] is true *)
            | _            -> acc in
          go acc (succ i) (pred n) in
    go None off
    (len cs - off) (* if [off] is > len cs the loop never terminates *)

@dinosaure Should we write a constant-time version of this for eqaf? (e.g. take non-optional offset, always update acc using constant-time select (maybe we should also expose our constant-time select code)?

EDIT(s): Formatting + elaboration

Request: AEAD_AES_256_GCM_SIV

Looking at libsodium docs,

Unlike other variants directly using the ChaCha20 cipher, generating a random nonce for each message is acceptable with this XChaCha20-based construction, provided that the output of the PRNG is indistinguishable from random data.

I am seeing similar claims elsewhere.

This seems like a desirable property, as I am concerned about key wearout in an application that is using AEAD. So, I'd like to request XChaCha20 support.

I don't know if XChaCha20 brings any new pitfalls of its own, and is studied well enough.

Use dune's variants and trick on the META file

This issue wants to solve an initial and systematic issue found into checkseum/digestif and try to prepare an easily move to mirage with dune. To contextualize a bit the goal of this issue, you probably should look into mirage/mirage#1024.

Come back to the dunification of MirageOS, the main and fully described difference of the compilation of an unikernel with ocamlbuild and with dune is the option: -output-complete-obj. The main difference is about static C libraries. Let back a bit about the diff.

Link an unikernel with ocamlbuild + ocamlfind

According the current status of MirageOS, a library with C stubs such as checkseum must fill a META file with some metadata to let the mirage tool to choose the right static C library according the target. mirage asks with ocamlfind these metadata and put at the link-time with -output-obj static libraries collected.

The compiler, at the link time and with -output-obj does not care about static libraries described into *.cmxa. This is why the mirage tool/ocamlbuild/ocaml can chooses the right static C libraries such as -lgmp-freestanding (for Solo5) according the target (even if zarith.cmxa describes -lgmp).

Link an unikernel with dune

However, dune strictly uses a new option of the compiler, -output-complete-obj and it seems that -output-obj will be deprecated. This new option change the behavior of the compiler where it wants to link the final main.o (the unikernel) with libraries described into *.cmxa used to produce the unikernel.

A link with zarith.cmxa with -output-complete-obj will try (at the compiler layer) to link with libgmp.a in any cases.

For a library such as checkseum (and mirage-crypto)

Of course, for any libraries which wants to provide C stubs, a compilation of the unikernel with -output-complete-obj constraints us to:

  1. still continue to provide a META file with such metadata to be compatible with MirageOS 3.*
  2. provides well-formed *.cmxa with right C libraries such as:
    • checkseum_freestanding.cmxa should link with -lcheckseum_freestanding
    • checkseum_xen.cmxa should link with -lcheckseum_xen

The second point is a requirement of the compiler due to the use of -output-complete-obj. The first point is the well-know requirement for MirageOS 3.*.

A question still exists however. Who and how we can choose between checkseum_freestanding and checkseum_xen according the target expected by the user? This is where dune can come and choose one of these libraries according an explicit expected variant.

I will not try to explain, again, variant but it unlock the ability for a user to choose an implementation (compiled object for Solo5, compiled object for Xen, etc.) according a common interface according a new field. dune is able to choose a default implementation if the field is missed (such as the unix target).

Under the use of variant, we have the ability to produce well-formed *.cmxa and each of them will have the same interface (technically, the same hash of the common interface).

A story about compatibility

However, if we choose to use variants and provide well-formed *.cmxa and help a bit the compiler to link with right static C libraries, we are not able to play with the META file. Of course, after some iterations, we did it (mostly on checkseum): you can look it here.

The final task

At the end, if we want to use dune to compile an unikernel, we must provides well-formed *.cmxa because of -output-complete-obj. The question about the way to choose which *.cmxa we will choose according the target is the main problem:

  • For MirageOS.3.*, this is done by ocamlfind
  • For a MirageOS with dune, it should be done by dune at least
  • An other solution exists with duniverse

To be smooth about such a transition, the first and the second point can live together. Of course, the solution is not perfect when:

  • we must hack the META file by ourselves
  • we must use dune's variants
  • the compilation to an executable (which uses the library with C stubs) with something else than dune will not properly work (due to the linking-trick).

However, I think it could be a good solution to pave the way to the dunification of MirageOS and give to use an intermediate step which is still compatible with both worlds.

Technically. what we should do

The task is to use dune's variants, so an update of:

  • freestanding/dune
  • xen/dune
  • src/native/dune
    is needed to specify which variants they are. Then, we must trick on the OPAM file to rightly put metadata needed by ocamlfind such as checkseum does.

So, for any questions, I'm free to go deeply into details and explain goals.

Build fails, preventing installation of irmin-unix on 2009 Mac

#=== ERROR while compiling mirage-crypto.0.8.10 ===============================#
# context     2.0.8 | macos/x86_64 | ocaml-base-compiler.4.11.1 | https://opam.ocaml.org#bea00a33
# path        ~/.opam/default/.opam-switch/build/mirage-crypto.0.8.10
# command     ~/.opam/opam-init/hooks/sandbox.sh build dune build -p mirage-crypto -j 1
# exit-code   1
# env-file    ~/.opam/log/mirage-crypto-14413-4519e5.env
# output-file ~/.opam/log/mirage-crypto-14413-4519e5.out
### output ###
# [...]
# struct _mc_cpu_features mc_detected_cpu_features = { 0 };
#                                                        ^
# native/detect_cpu_features.c:18:13: error: use of undeclared identifier 'bit_PCLMUL'
#   if (ecx & bit_PCLMUL)
#             ^
# native/detect_cpu_features.c:22:13: error: use of undeclared identifier 'bit_AES'
#   if (ecx & bit_AES)
#             ^
# native/detect_cpu_features.c:29:15: error: use of undeclared identifier 'bit_RDSEED'
#     if (ebx & bit_RDSEED)
#               ^
# 1 warning and 3 errors generated.

release 0.7.0

issues to address:

  • run-time instead of build-time feature detection for aesni (issue #45) done via #53
  • revise entropy / PRNG
  • integrate #48 for cross-building for mirageos4 (on hold)
  • point from "unseeded generator" exception to how to seed the generator (either in docs or the exception itself) -- happened e.g. on mirage if you use Mirage_crypto_rng.generate without using the random device in your unikernel (ssh-agent had this issue)
  • make powm_sec optional (i.e. being able to disable it), there are scenarios where paying the 20% isn't worth it -- esp. since it does not lead to "all is constant time now"
  • replace ct_find_uint8 by eqaf (>= 0.7.0) done via #52
  • 32bit support (requested in #60) -- done in #65

feel free to comment on this issue about more tasks to include in the next (major) release.

improve CI setup (ocamlformat, doc target)

  • use + require ocamlformat (evaluate whether it it stable yet -- not keen to upgrade every other week to a slightly different format)?
  • build doc target (to spot warnings and errors)

--> is this possible with ocaml-ci out of the box?

towards a release

Below is a draft plan of "what we should do before an initial release". Let us please discuss if there are items missing from the list, or whether some of the items should be skipped for a release.

The set of changes we should aim for an initial release are in my opinion:

  • decide on the main module name (being it Mirage_crypto or just Crypto)? It'll be Mirage_crypto.
  • finish renaming of the library (best case: have nocrypto and mirage-crypto coinstallable / colinkable (requires distinct C symbols as well)
  • port to dune (there's earlier work, https://github.com/mirleft/ocaml-nocrypto/tree/dune is a fine start imho) see #4
  • get freestanding + xen support back (see https://github.com/dinosaure/ocaml-nocrypto/commits/dune and https://github.com/hannesm/ocaml-nocrypto/commits/awa-future) -- for now not using variants (i.e. stay compatible with mirage 3.7) see #4
  • revert the "remove sexp" commit a58c653 (if desired we can remove the sexp conversions at a later stage, but e.g. TLS uses them) see #4
  • address the various security things, see #3
  • setup maintainership and code review guidelines for this repository (approval is required for PRs, maintainers have write permission now, CI for linux & macOS & FreeBSD are in place)
  • spread into multiple packages -- the main motivation is to separate the stuff depending on the pretty big zarith / libgmp (asymmetric crypto) to allow Fortuna (the PRNG) being used by all MirageOS unikernels (see https://github.com/hannesm/ocaml-nocrypto/commits/split for an initial attempt) -- this can as well be a good preparation for reducing the overlap between crypto and digestif -- see also https://github.com/mirleft/ocaml-nocrypto/commits/breakage
  • ensure mirage-crypto-* works for reverse dependencies of nocrypto

at some later point, we should:

  • write microbenchmarks and run with released versions (and openssl) as baseline, to evaluate potential performance regression before a release
  • discuss the underlying storage data structure (atm Cstruct.t, digestif uses String/Bytes/Bigarray)
  • de-duplicate the hash implementations between crypto and digestif
  • define (or revise) a DH interface (so fiat and x25519 and this FFDHE can share the same module type) -- imho these libraries should be integrated into this repository as well
  • define an AEAD interface (so CCM/GCM/potentially poly1305/Chacha20 can share it)
  • remove the compile-time CPU feature detection (using cpuid), instead defer to runtime CPU detection (without performance regression, i.e. only do it once, not on every call to AES)

Compile errors on aarch32

I found dune build on aarch32 results in multiple errors due to __uint128_t not supported by 32-bit gcc.

imada@ubuntu:~/mirage/mirage-crypto$ dune build
      ocamlc freestanding/ghash_generic.o (exit 2)
...
src/native/ghash_generic.c:23:14: error: unknown type name ‘__uint128_t’
src/native/ghash_generic.c:21:36: error: ‘__uint128_t’ undeclared here (not in a function); did you mean ‘__int128’?
src/native/ghash_generic.c:23:30: note: in expansion of macro ‘__set_uint128_t’
src/native/ghash_generic.c:23:47: error: expected ‘)’ before numeric constant
src/native/ghash_generic.c:21:49: note: in definition of macro ‘__set_uint128_t’
...
...

The current mirage-crypto-entropy.opam indicates 32-bit arm and x86 as available architecture, x86_32 will have the same errors too.

available: [
  arch = "arm" | arch = "x86_32" | arch = "x86_64" | arch = "arm64"
]

7d67013 seems the first commit which employed __uint128_t.

RSA priv validation fails on Gcloud private keys

I'm having trouble constructing keys using Rsa.priv (via the x509 library), specifically using the RSA private keys embedded in Google's service account JSON credentials.

(This is for our ocaml-gcloud library.)

I haven't been able to reproduce this using private keys I've generated myself using openssl genpkey.

Here's an example (revoked :)) pk from Google that fails to validate:

#require "cstruct";;
#require "x509";;

let key = {|
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC0Iuq7GtFgSVnO
CG27r4pN5Xsqz7hzomdNLM+hadpbOGZC0fa7bdtXGcKIZs8IZg8ZFjmGvxu3UX8O
JCKURbK5UZXKWrsQjwFivr+YJL3zISqwWh3ibIHp/bs/6azYSW9AZaPhRr/BD2M4
V05C+sL0CBSXX3b+Rr23rW57jqkYAP9TpFGZU2VuqBql/kcD32YNRuVE9ak1Gudt
Du4O9G0EGuOFXIxcPa6TRzVBPtenRSzbeij4Iqf04jM+FgaFz7cUM1fjvEWIuvEV
1vNwssEPN7sXTYqpWnQOGHI70an5pJ75npo8ZKrwVzAFotSxDPNbBTR0D8vBsFhG
TlmwgtJ9AgMBAAECggEAGJ+fQ5VOYqGUN5A6Y8oCl1RTqk37sj7UbR2/ghqEoSyL
+f1Wg1dogLcCOwAGs+izjqPVmEA+aygmPIoe+fKvFBr9ZUxSvtg1gch+Sy9WkcoK
WlHvPNjFR3WKJ5nrKSOcpApgxPYVVzAhyX1RsuExTgdevTRtASQtYdLAw/4DykZ5
58nbfMLa9cZ0zu+BTIkKhAAEvjMVnzvuDQWhAShLMQISGbcHVApTzSbj7nCR/tn0
2B7znmu/YcHTBsNdee1Ic9/cfLWWueGeYt1z2RUo6h9H4ILJ8Vju/pUqCAUFj2c0
tTLs1pKgxbQv/PEW1OKbeM1MqO6ya0buCJy++up9xwKBgQDbKnzQCRtmSIRSCsHW
IYeWwIWvhrQIaQuUtaJ5A/42sKPvIu/HdoScZuZzXsC+WIsmr1XEFUSaxJnAbDhM
73fuUdNlzoQa+dw3x8eoL2KPhHUMgXgGR//eMMegorzSwR7Lmeu2w1G7UZFVfRby
6cqBMMvExoMT017UvdEegwoz3wKBgQDSaTNM2eSIlSHWilaudvjzFyFnoYrNd4ep
52XiSBA/3KMlBv3ZbWmiNlwgKZq77DYnUZGMYdXXbB2edAK5a/ikphNLPRhn1zNq
hVEDXuOwkcyGyNol1P2z9G3n9B+rNy+1RYFAKPJ9/eAqtuxj6kgNDPReXk/a+vtj
+DMsWzGlIwKBgAieLhQ8F3C5L0LOm3qhDOTXoyoYwOGHx+XMEpxxlMBvx7JyjD0q
ouJHhY5JzohtkOMvh87TC0SOsIEJgFk+HVgorYhWS4mIA6nJ2Eb7vgNosPWR7bdJ
g30oK+FcJNKgt2ZIIiWonoEgHvfemFVq7gSQd6LAL41LBXKWGC/79R2/AoGACUGN
eyz+q697zJdLVuNu8iqrUoa9t2oxspy2U6z94gFPv/o9wonYosUnalbKMsgiXbpt
37ISGSbtaqIJ2KRSTNPtd1rZrv+9iEsTFEXhWEwhpjBBwHZNLtRq3VBU8FA+Lgg/
tlXWzQoVCWwAnCibQM+4FEqr0qNF2dD6V1IvrecCgYEAr8VENgxbQ+mZq6bIfMqC
vCj0DNppYs0llOlu/9JZZzEHnas9afg+rNlK/Hd5iMgzJ/0bxlI+u/G3do2QJ8dP
z5ewonMpLxmcxWoB/47FdaNhtiMpZkwpi7EOvapzN8jgr8DWeMTl2aA4iMEOk0lj
v7+MqvYwLMfQTrTzGu9VjFo=
-----END PRIVATE KEY-----
|};;

let key_c = Cstruct.of_string key;;

X509.Private_key.decode_pem key_c

And the result:

Rresult.Error (`Msg "bad RSA private key d <> e ^ -1 mod (p - 1) * (q - 1)")

I've seen this comment:

{b Note} The key layout assumes that [p > q], which affects the quantity
[q'] (sometimes called [u]), and the computation of the private transform.
Some systems assume otherwise. When using keys produced by a system that
computes [u = p^(-1) mod q], either exchange [p] with [q] and [dp] with
[dq], or re-generate the full private key using
{{!priv_of_primes}[priv_of_primes]}.

And I tried swapping p<->q and dp<->dq (in the implementation of x509) as suggested but then q' fails to validate, which leads me to suspect that is not the issue, although I am no expert.

As a workaround I have forked x509 to reconstruct the derived parameters using Rsa.priv_of_primes, which Google accepts: imandra-ai/ocaml-x509@db01a2a

I'm not sure whether this is an issue with Rsa.priv, or with Google's RSA keys. Any insight would be much appreciated!

ARM TRNGs

Not for now, but in the future ARM is getting RDSEED-like instructions (don't believe there are currently any chips available with this 8.5-A ISA):
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-a-profile-architecture-2018-developments-armv85a

Armv8.5-A also contains other small features, including:
Random Number instructions – providing Deterministic and True Random Numbers conforming to various National and International Standards.

This would go in caml_cpu_checked_random and caml_cpu_unchecked_random in src/native/entropy_cpu_stubs.c

add AMD phenom CI

Report #93 shows that we should have a CI with a x86 CPU that does not have too many CPU features (esp. no PCLMUL / SSSE3). The idea would be to use qemu-x86_64-static -cpu phenom to execute the test suite on such an emulated CPU.

Document the responsibilities of the consumer

We should document the responsibilities of the consumer when it comes to providing inputs for various functions, e.g. what input validation the consumer is up to the user versus the user can expect the library to complain about.

This ties in with developing / documenting the threat models we consider for each API endpoint.

Consider the following example where an attacker can provide a (very small) public key, a message, and an alleged signature to a program that performs PKCS1 signature validation.

We will not allow our own users to generate such a signature (SHA256) with a key less than 489 bits, but we are happy to attempt validation, in the worst case with an endless loop as the result.

It follows that the user should not pass in "too small keys," or alternatively that we should perform validation thereof. In either case we should probably detail somewhere what "too small" entails.

#require "mirage-crypto-pk";;
#require "mirage-crypto-rng.unix";;
Mirage_crypto_rng_unix.initialize ();;
let rec attacker_provides keylen =
  (* bad person provides: *)
  let open Mirage_crypto_pk.Rsa in
  let small_priv = generate ~e:(Z.of_int 3) keylen in
  let small_pub = pub_of_priv small_priv in
  let hash = `SHA256 in
  let msg = Cstruct.(of_string @@ String.make (keylen/8) 'a') in
  let signature =  Cstruct.(of_string @@ String.make (keylen/8) 'a') in
  small_pub, hash, msg, signature
and verifier_computes bad_key_len =
  let pub, hash_algo, msg, signature = attacker_provides bad_key_len in
  assert (List.exists ((=) hash_algo)  [`SHA256] ); (* consumer discards MD5 etc *)
  let digest = Mirage_crypto.Hash.digest hash_algo msg in
   Mirage_crypto_pk.Rsa.PKCS1.verify ~key:pub ~hashp:(fun x -> x = hash_algo)
   (`Digest digest) ~signature
;;

verifier_computes 15;;
(* As expected: - : bool = false *)

verifier_computes 8;;
(* Endless loop. A consumer has no way to recover from this. *)

verifier_computes 16;;
(* undocumented exception from Mirage_Crypto_pk.Rsa.PKCS1.verify:
Exception: (Invalid_argument "invalid bounds in Cstruct.get_uint8 [0,2](2) off=2 len=1")
*)

mirage-crypto raises an Invalid Instruction on AMD Phenom II X4 955

Even if an AMD Phenom II X4 955 is recognized as a x86_64 processor, it seems that it's not possible to use -maes and -mpclmul (at least, the lscpu does not show such extra instruction). SSE3 is missing too. It seems that config/cfg.ml should be more clever on such processor.

AEAD interface improvements

It would be good to enhance the interface with:

val of_secret : Cstruct.t -> key
(** [of_secret k] validates [k] to be of appropriate size etc. *)

val tag_size : int
(** [tag_size] is the size in octets of the authentication tag. *)

To achieve this, CCM needs to take the maclen as functor argument (instead of as argument to of_secret). This is fine since the call site usually defines (by protocol spec) how long the tag should be. Unclear how to avoid defining CCM_4, CCM_6, CCM_8, CCM_10, CCM_12, CCM_14, CCM_16 - maybe allow the user to construct them themselves (i.e. exposing S.Core and CCM_of).

security issues from nocrypto repository

Linking error while installing `mirage-crypto-pk` on macOS Big Sur

I get the following error while installing mirage-crypto-pk (which is one of the dependencies of https://github.com/ulrikstrid/reason-jose/):

<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>
[ERROR] The compilation of mirage-crypto-pk failed at "/Users/jayesh/.opam/opam-init/hooks/sandbox.sh build dune build -p mirage-crypto-pk -j 5".

#=== ERROR while compiling mirage-crypto-pk.0.10.1 ============================#
# context     2.0.8 | macos/x86_64 | ocaml-base-compiler.4.12.0 | https://opam.ocaml.org#80188570
# path        ~/.opam/4.12.0/.opam-switch/build/mirage-crypto-pk.0.10.1
# command     ~/.opam/opam-init/hooks/sandbox.sh build dune build -p mirage-crypto-pk -j 5
# exit-code   1
# env-file    ~/.opam/log/mirage-crypto-pk-63734-e7966f.env
# output-file ~/.opam/log/mirage-crypto-pk-63734-e7966f.out
### output ###
#     ocamlopt .ppx/e5c62d576feb9cf4645d7d03ed58d831/ppx.exe (exit 2)
# (cd _build/default && /Users/jayesh/.opam/4.12.0/bin/ocamlopt.opt -g -w -24 -o .ppx/e5c62d576feb9cf4645d7d03ed58d831/ppx.exe /Users/jayesh/.opam/4.12.0/lib/ocaml/compiler-libs/ocamlcommon.cmxa /Users/jayesh/.opam/4.12.0/lib/ocaml-compiler-libs/common/ocaml_common.cmxa /Users/jayesh/.opam/4.12.0/lib/ocaml-compiler-libs/shadow/ocaml_shadow.cmxa /Users/jayesh/.opam/4.12.0/lib/ocaml-migrate-parse[...]
# Undefined symbols for architecture x86_64:
#   "____chkstk_darwin", referenced from:
#       _caml_md5_channel in libasmrun.a(md5.n.o)
#       _caml_sys_getcwd in libasmrun.a(sys.n.o)
#       _ff_allocate in libasmrun.a(freelist.n.o)
# ld: symbol(s) not found for architecture x86_64
# clang-7: error: linker command failed with exit code 1 (use -v to see invocation)
# File "caml_startup", line 1:
# Error: Error during linking (exit code 1)

Any pointers for me?

more robust CPU feature compilation and runtime selection

at the moment (with #96 merged):

  • __builtin_bswap is avoided (since together with -mssse3 it leads to SSSE3 instructions that won't work on e.g. AMD Phenom II)
  • chacha source is copied to be compiled twice, once with and once without -mssse3

newer compilers with more analysis may optimize even more code into ssse3 instructions (of other hashes / ...).

to avoid this potential miscompilation, "all" C code should be compiled twice:

  • once with machine intrinsics flags that are useful (atm ssse3/aes/pclmul)
  • once without any machine-dependent intrinsics

then all entries (called from OCaml) should be runtime dispatched on the specific feature flags.

the issue with the above approach is that it is not yet clear which CPU features could be used in which settings and which features are useful (thinking of SSSE4 etc. as well). to avoid a huge matrix, time should be used to research what is useful.

A way to get the global `g` state from the initialization of the RNG device.

Currently, with MirageOS, it's not possible to get the g state from the initialization (and be able to pass it to some others computations). It should be very nice for the initialize function to return the g state - and then, get it from the start function of an unikernel instead of an unit value. WDYT? The patch should be small but I think it breaks the API.

RNG initialization inconsistencies

as remarked by @talex5 in #155

Why is a generator necessary here? rng/lwt/mirage_crypto_rng_lwt.mli doesn't have one, nor a g argument. Though the Mirage one does. And Unix doesn't. Odd.

For completeness, the APIs

Mirage_crypto_rng_unix: val initialize : unit -> unit

Mirage_crypto_rng_lwt: val initialize : ?sleep:int64 -> unit -> unit

Mirage_crypto_rng_async: val initialize : ?g:'a -> ?time_source:Synchronous_time_source.t -> ?sleep:Time_ns.Span.t -> 'a Mirage_crypto_rng.generator -> unit

(* functorized over Mirage_time.S (for sleep_ns) and monotonic clock (Mirage_clock.MCLOCK) for limit the amount of reseedings *)
Mirage_crypto_rng_mirage: val initialize : ?g:'a -> ?sleep:int64 -> 'a Mirage_crypto_rng.generator -> unit Lwt.t

Mirage_crypto_rng_eio: val run : ?g:'a -> ?sleep:int64  -> 'a Mirage_crypto_rng.generator -> <env; ..> -> (unit -> 'b) -> 'b

The absence of ~sleep from the Unix implementation is expected, since there's no periodic reseeding happening (to avoid spawning threads, ..).

entropy: feed qubes random-seed at startup

see mirage/mirage-qubes#34 for a discussion, basically there is a value for the key /qubes-random-seed in QubesDB that is provided by the host (once at startup!) to the VM to have some random bytes. this means that the rng is only available once QubesDB is up and running (does QubesDB initialization require randomness?), or the QubesDB connect code should enrich the (already seeded) RNG with some more entropy.

it would need to be integrated into entropy/, leading to an enriched API for target-dependent entropy harvesting (/bootstrapping).

test failures on arm32

the last successful run (https://ci.ocamllabs.io/github/mirage/mirage-crypto/commit/6b91b5823850830deeefd7e7df3ddb250c46a14b/variant/debian-10-4.12_arm32) is attached. success-mirage-crypto.txt

The error is:

test_pk_runner alias tests/runtest (exit 1)
(cd _build/default/tests && ./test_pk_runner.exe)
.......................................................................................................................................................................................................................................................................................................................................................EEE.............
==============================================================================
Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:2:selftest.

File "/src/_build/default/tests/oUnit-All-builder#00.log", line 2487, characters 1-1:
Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:2:selftest (in the log).

Worker stops running: Killed by signal -22
------------------------------------------------------------------------------
==============================================================================
Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:1:selftest.

File "/src/_build/default/tests/oUnit-All-builder#00.log", line 2468, characters 1-1:
Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:1:selftest (in the log).

Worker stops running: Killed by signal -22
------------------------------------------------------------------------------
==============================================================================
Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:0:selftest.

File "/src/_build/default/tests/oUnit-All-builder#00.log", line 2449, characters 1-1:
Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:0:selftest (in the log).

Worker stops running: Killed by signal -22
------------------------------------------------------------------------------
Ran: 359 tests in: 11.80 seconds.
FAILED: Cases: 359 Tried: 359 Errors: 3 Failures: 0 Skip:  0 Todo: 0 Timeouts: 0.
test_symmetric_runner alias tests/runtest (exit 1)
(cd _build/default/tests && ./test_symmetric_runner.exe)
accel: 
.......................................................................................................................................................................................E
==============================================================================
Error: All:1:Hash:6:regression:0.

File "/src/_build/default/tests/oUnit-All-builder#00.log", line 1308, characters 1-1:
Error: All:1:Hash:6:regression:0 (in the log).

Worker stops running: Killed by signal -22
------------------------------------------------------------------------------
Ran: 184 tests in: 1.29 seconds.
FAILED: Cases: 184 Tried: 184 Errors: 1 Failures: 0 Skip:  0 Todo: 0 Timeouts: 0.
"/usr/bin/linux32" "/bin/sh" "-c"
"opam exec -- dune build @install @check @runtest && rm -rf _build" failed with exit status 1
2021-10-20 10:53.24: Job failed: Failed: Build failed
2021-10-20 10:53.24: Log analysis:
2021-10-20 10:53.24: >>> Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:2:selftest. (score = 10)
2021-10-20 10:53.24: >>> Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:2:selftest (in the log). (score = 10)
2021-10-20 10:53.24: >>> Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:1:selftest. (score = 10)
2021-10-20 10:53.24: >>> Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:1:selftest (in the log). (score = 10)
2021-10-20 10:53.24: >>> Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:0:selftest. (score = 10)
2021-10-20 10:53.24: >>> Error: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:0:selftest (in the log). (score = 10)
2021-10-20 10:53.24: >>> Error: All:1:Hash:6:regression:0. (score = 10)
2021-10-20 10:53.24: >>> Error: All:1:Hash:6:regression:0 (in the log). (score = 10)
2021-10-20 10:53.24: All:3:RSA:3:RSA-OAEP(SHA1)-ENC:2:selftest.

where the hash test (regression) is unaligned cstruct access -- does this fail on arm32?
and what changed in the CI system so that the error is visible now? What is signal -22 on Linux/arm32?

full failure log at failure-mirage-crypto.txt

Split sub libraries in `mirage-crypto-rng` into individual packages

At the moment mirage-crypto-rng package contains sub-libraries in the same package.

  1. mirage-crypto-rng.lwt
  2. mirage-crypto-rng.unix

This results in pulling in extra dependencies where they are not needed, for example mirage-crypto-rng-async and the new package mirage-crypto-rng-eio packages pulling in at least unix and lwt where they are not needed. Should these sub libraries be split into their own separate pacakges? i.e. mirage-crypto-rng-lwt and mirage-crypto-rng-unix ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.