summaryrefslogtreecommitdiffstats
path: root/comm/third_party/libgcrypt/random
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/libgcrypt/random
parentInitial commit. (diff)
downloadthunderbird-upstream.tar.xz
thunderbird-upstream.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/libgcrypt/random')
-rw-r--r--comm/third_party/libgcrypt/random/ChangeLog-2011191
-rw-r--r--comm/third_party/libgcrypt/random/Makefile.am69
-rw-r--r--comm/third_party/libgcrypt/random/Makefile.in744
-rw-r--r--comm/third_party/libgcrypt/random/jitterentropy-base-user.h134
-rw-r--r--comm/third_party/libgcrypt/random/jitterentropy-base.c791
-rw-r--r--comm/third_party/libgcrypt/random/jitterentropy.h148
-rw-r--r--comm/third_party/libgcrypt/random/rand-internal.h148
-rw-r--r--comm/third_party/libgcrypt/random/random-csprng.c1367
-rw-r--r--comm/third_party/libgcrypt/random/random-daemon.c336
-rw-r--r--comm/third_party/libgcrypt/random/random-drbg.c2668
-rw-r--r--comm/third_party/libgcrypt/random/random-system.c250
-rw-r--r--comm/third_party/libgcrypt/random/random.c584
-rw-r--r--comm/third_party/libgcrypt/random/random.h79
-rw-r--r--comm/third_party/libgcrypt/random/rndegd.c290
-rw-r--r--comm/third_party/libgcrypt/random/rndhw.c230
-rw-r--r--comm/third_party/libgcrypt/random/rndjent.c389
-rw-r--r--comm/third_party/libgcrypt/random/rndlinux.c366
-rw-r--r--comm/third_party/libgcrypt/random/rndunix.c937
-rw-r--r--comm/third_party/libgcrypt/random/rndw32.c1030
-rw-r--r--comm/third_party/libgcrypt/random/rndw32ce.c199
20 files changed, 10950 insertions, 0 deletions
diff --git a/comm/third_party/libgcrypt/random/ChangeLog-2011 b/comm/third_party/libgcrypt/random/ChangeLog-2011
new file mode 100644
index 0000000000..cd45c3d666
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/ChangeLog-2011
@@ -0,0 +1,191 @@
+2011-12-01 Werner Koch <wk@g10code.com>
+
+ NB: ChangeLog files are no longer manually maintained. Starting
+ on December 1st, 2011 we put change information only in the GIT
+ commit log, and generate a top-level ChangeLog file from logs at
+ "make dist". See doc/HACKING for details.
+
+2011-09-08 Werner Koch <wk@g10code.com>
+
+ * rndlinux.c (_gcry_rndlinux_gather_random): Don't use select if
+ the fd number is too high. Reported by Jakub Bogusz.
+
+2010-10-18 Werner Koch <wk@g10code.com>
+
+ * rndw32.c (registry_poll): Disable performace fata gathering if
+ GNUPG_RNDW32_NOPERF has been set.
+
+2010-04-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * rndw32ce.c (fillup_buffer): Rewrite without using nested
+ functions, which are broken on arm/cegcc.
+
+2010-04-12 Brad Hards <bradh@frogmouth.net> (wk)
+
+ Spelling fixes.
+
+2010-03-24 Werner Koch <wk@g10code.com>
+
+ * rndw32.c: Revert all changes from 2010-01-21.
+
+ * rndw32ce.c: New.
+ * Makefile.am (EXTRA_librandom_la_SOURCES): Add it.
+ * random-csprng.c (getfnc_gather_random)
+ (getfnc_fast_random_poll) [USE_RNDW32CE]: Use rndw32ce.
+
+2010-01-21 Werner Koch <wk@g10code.com>
+
+ * rndw32.c (read_mbm_data) [W32CE]: Do not build.
+ (slow_gatherer) [W32CE]: Do not call read_mbm_data.
+ (_gcry_rndw32_gather_random_fast) [W32CE]: Exclude some calls.
+ (_gcry_rndw32_gather_random): Adjust version test for WindowsCE.
+
+2009-12-10 Werner Koch <wk@g10code.com>
+
+ * rndw32.c (system_is_w2000): New.
+ (_gcry_rndw32_gather_random): Set it.
+ (slow_gatherer): Ignore SystemObjectInformation on W2000. Fixes
+ bug#1167.
+
+2009-07-09 Werner Koch <wk@g10code.com>
+
+ * rndlinux.c (_gcry_rndlinux_gather_random): Print real values for
+ the progess function and call it before blocking. Suggested by
+ Christian Grothoff.
+ * rndunix.c (slow_poll): Add similar, but not yet functional, code.
+
+2009-07-02 Werner Koch <wk@g10code.com>
+
+ * rndhw.c (poll_padlock): Asm change from Fedora.
+
+2009-01-22 Werner Koch <wk@g10code.com>
+
+ * random.c (_gcry_random_deinit_external_test): Do not return a
+ value. Reported Albert Chin.
+
+2008-09-16 Werner Koch <wk@g10code.com>
+
+ * random-fips.c (x931_aes_driver): No re-seeding with test contexts.
+ (_gcry_rngfips_init_external_test): Fix setting of test_dt_ptr.
+ (struct rng_context): Add flag TEST_NO_DUP_CHECK.
+ (x931_aes_driver): Use that flag.
+ (_gcry_rngfips_init_external_test): Add arg FLAGS and use it to
+ modify the test.
+ * random.c (_gcry_random_init_external_test): Pass FLAGS.
+
+2008-09-15 Werner Koch <wk@g10code.com>
+
+ * random.c (_gcry_random_init_external_test): New.
+ (_gcry_random_run_external_test): New.
+ (_gcry_random_deinit_external_test): New.
+ * random-fips.c (struct rng_context): Turn TEST_DT_COUNTER into a
+ 32 bit integer.
+ (x931_get_dt): Ditto.
+ (selftest_kat): Intialize it accordingly.
+ (_gcry_rngfips_init_external_test): New.
+ (_gcry_rngfips_run_external_test): New.
+ (_gcry_rngfips_deinit_external_test): New.
+
+2008-09-05 Werner Koch <wk@g10code.com>
+
+ * random.c (_gcry_random_selftest): Return success if not in fips
+ mode.
+
+2008-09-01 Werner Koch <wk@g10code.com>
+
+ * random-fips.c (x931_get_dt) [W32]: Do not use getppid.
+ (get_entropy): Prepare for use under Windows.
+ (_gcry_rngfips_selftest): Ditto.
+ (entropy_collect_cb): Make sure that the gatherer never overflows
+ the buffers.
+
+2008-08-29 Werner Koch <wk@g10code.com>
+
+ * random-fips.c (SEED_TTL): New.
+ (struct rng_context): Add USE_COUNTER, remove NEED_STRONG_ENTROPY.
+ (x931_aes_driver): Do re-seeding if required.
+ (x931_generate_key, x931_generate_seed): Factor common code out to ..
+ (get_entropy): .. new. Always use /dev/random.
+ (x931_generate_key): Seed key for nonce_context from std_rng_context.
+ (x931_reseed): New. Seed nonce context from std_rng_context.
+ (get_random): Use x931_reseed.
+ (_gcry_rngfips_selftest): Return an error if no /dev/radom support
+ has been compiled in.
+ (get_random): Remove locking.
+ (_gcry_rngfips_randomize, _gcry_rngfips_create_nonce): Lock here.
+
+2008-08-28 Werner Koch <wk@g10code.com>
+
+ * random-daemon.c (connect_to_socket): Use GPG_ERR_ENAMETOOLONG.
+
+2008-08-25 Werner Koch <wk@g10code.com>
+
+ * random-fips.c (x931_aes): Take datetime_GT from an arg.
+ (x931_aes_driver): Call x931_get_dt here.
+ (x931_get_dt): Implement the KAT hack.
+ (x931_generate_seed): Copy the seed value to the provided buffer.
+ (selftest_kat): New.
+
+2008-08-22 Werner Koch <wk@g10code.com>
+
+ * random.c (_gcry_update_random_seed_file): Move operational check
+ to _gcry_vcontrol.
+ (_gcry_fast_random_poll): Ditto.
+ (_gcry_random_selftest): New.
+ * random-fips.c (_gcry_rngfips_selftest): New.
+
+2008-08-21 Werner Koch <wk@g10code.com>
+
+ * random-fips.c: Finish implementation.
+
+2008-08-15 Werner Koch <wk@g10code.com>
+
+ * random-fips.c: New.
+
+ * random-csprng.c (process-cb, progress_cb_data): Move to
+ random.c.
+ (_gcry_register_random_progress, _gcry_random_progress): Ditto.
+ (_gcry_random_initialize): Rename to _gcry_rngcsprng_initialize.
+ (_gcry_random_dump_stats): Rename to _gcry_rngcsprng_dump_stats.
+ (_gcry_secure_random_alloc): Rename to
+ _gcry_rngcsprng_secure_alloc.
+ (_gcry_enable_quick_random_gen): Rename to
+ _gcry_rngcsprng_enable_quick_gen.
+ (_gcry_set_random_daemon_socket): Rename to
+ _gcry_rngcsprng_set_daemon_socket.
+ (_gcry_use_random_daemon): Rename to _gcry_rngcsprng_use_daemon.
+ (_gcry_random_is_faked): Rename to _gcry_rngcsprng_is_faked.
+ (gcry_random_add_bytes): Rename to _gcry_rngcsprng_add_bytes.
+ (gcry_random_bytes): Remove
+ (gcry_random_bytes_secure): Remove.
+ (gcry_randomize): Rename to _gcry_rngcsprng_randomize.
+ (_gcry_set_random_seed_file): Rename to
+ _gcry_rngcsprng_set_seed_file.
+ (_gcry_update_random_seed_file): Rename to
+ _gcry_rngcsprng_update_seed_file.
+ (_gcry_fast_random_poll): Rename to _gcry_rngcsprng_fast_poll.
+ (gcry_create_nonce): Rename to _gcry_rngcsprng_create_nonce.
+
+ * random.c: Factor all code out to random-csprng.c and implement
+ wrapper functions.
+
+2008-07-05 Werner Koch <wk@g10code.com>
+
+ * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h *
+ random.c, rndegd.c, rndlinux.c, rndw32.c: Move from ../cipher/ to
+ here.
+ * Makefile.am: New.
+
+ Copyright 2008, 2009 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Local Variables:
+buffer-read-only: t
+End:
diff --git a/comm/third_party/libgcrypt/random/Makefile.am b/comm/third_party/libgcrypt/random/Makefile.am
new file mode 100644
index 0000000000..7e6e6f032f
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/Makefile.am
@@ -0,0 +1,69 @@
+# Makefile for cipher modules
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of Libgcrypt.
+#
+# Libgcrypt is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Libgcrypt is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+# Process this file with automake to produce Makefile.in
+
+# Need to include ../src in addition to top_srcdir because gcrypt.h is
+# a built header.
+AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
+AM_CFLAGS = $(GPG_ERROR_CFLAGS)
+
+noinst_LTLIBRARIES = librandom.la
+
+GCRYPT_MODULES = @GCRYPT_RANDOM@
+
+librandom_la_DEPENDENCIES = $(GCRYPT_MODULES)
+librandom_la_LIBADD = $(GCRYPT_MODULES)
+
+librandom_la_SOURCES = \
+random.c random.h \
+rand-internal.h \
+random-csprng.c \
+random-drbg.c \
+random-system.c \
+rndjent.c \
+rndhw.c
+
+if USE_RANDOM_DAEMON
+librandom_la_SOURCES += random-daemon.c
+endif USE_RANDOM_DAEMON
+
+
+EXTRA_librandom_la_SOURCES = \
+rndlinux.c \
+rndegd.c \
+rndunix.c \
+rndw32.c \
+rndw32ce.c \
+jitterentropy-base.c jitterentropy.h jitterentropy-base-user.h
+
+
+# The rndjent module needs to be compiled without optimization. */
+if ENABLE_O_FLAG_MUNGING
+o_flag_munging = sed -e 's/-O\([1-9sg][1-9sg]*\)/-O0/g' -e 's/-Ofast/-O0/g'
+else
+o_flag_munging = cat
+endif
+
+rndjent.o: $(srcdir)/rndjent.c jitterentropy-base-user.h \
+ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
+ `echo $(COMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
+
+rndjent.lo: $(srcdir)/rndjent.c jitterentropy-base-user.h \
+ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
+ `echo $(LTCOMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
diff --git a/comm/third_party/libgcrypt/random/Makefile.in b/comm/third_party/libgcrypt/random/Makefile.in
new file mode 100644
index 0000000000..f9489de14b
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/Makefile.in
@@ -0,0 +1,744 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile for cipher modules
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of Libgcrypt.
+#
+# Libgcrypt is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Libgcrypt is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+# Process this file with automake to produce Makefile.in
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@USE_RANDOM_DAEMON_TRUE@am__append_1 = random-daemon.c
+subdir = random
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cc_for_build.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/socklen.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__librandom_la_SOURCES_DIST = random.c random.h rand-internal.h \
+ random-csprng.c random-drbg.c random-system.c rndjent.c \
+ rndhw.c random-daemon.c
+@USE_RANDOM_DAEMON_TRUE@am__objects_1 = random-daemon.lo
+am_librandom_la_OBJECTS = random.lo random-csprng.lo random-drbg.lo \
+ random-system.lo rndjent.lo rndhw.lo $(am__objects_1)
+librandom_la_OBJECTS = $(am_librandom_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/jitterentropy-base.Plo \
+ ./$(DEPDIR)/random-csprng.Plo ./$(DEPDIR)/random-daemon.Plo \
+ ./$(DEPDIR)/random-drbg.Plo ./$(DEPDIR)/random-system.Plo \
+ ./$(DEPDIR)/random.Plo ./$(DEPDIR)/rndegd.Plo \
+ ./$(DEPDIR)/rndhw.Plo ./$(DEPDIR)/rndjent.Plo \
+ ./$(DEPDIR)/rndlinux.Plo ./$(DEPDIR)/rndunix.Plo \
+ ./$(DEPDIR)/rndw32.Plo ./$(DEPDIR)/rndw32ce.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(librandom_la_SOURCES) $(EXTRA_librandom_la_SOURCES)
+DIST_SOURCES = $(am__librandom_la_SOURCES_DIST) \
+ $(EXTRA_librandom_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
+FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
+FGREP = @FGREP@
+GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
+GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
+GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
+GCRYPT_KDFS = @GCRYPT_KDFS@
+GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
+GCRYPT_RANDOM = @GCRYPT_RANDOM@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDADD_FOR_TESTS_KLUDGE = @LDADD_FOR_TESTS_KLUDGE@
+LDFLAGS = @LDFLAGS@
+LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
+LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
+LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
+LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
+LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
+LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
+LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
+LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
+LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
+LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
+LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MPI_SFLAGS = @MPI_SFLAGS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTH_CFLAGS = @PTH_CFLAGS@
+PTH_CONFIG = @PTH_CONFIG@
+PTH_LIBS = @PTH_LIBS@
+RANLIB = @RANLIB@
+RC = @RC@
+RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Need to include ../src in addition to top_srcdir because gcrypt.h is
+# a built header.
+AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
+AM_CFLAGS = $(GPG_ERROR_CFLAGS)
+noinst_LTLIBRARIES = librandom.la
+GCRYPT_MODULES = @GCRYPT_RANDOM@
+librandom_la_DEPENDENCIES = $(GCRYPT_MODULES)
+librandom_la_LIBADD = $(GCRYPT_MODULES)
+librandom_la_SOURCES = random.c random.h rand-internal.h \
+ random-csprng.c random-drbg.c random-system.c rndjent.c \
+ rndhw.c $(am__append_1)
+EXTRA_librandom_la_SOURCES = \
+rndlinux.c \
+rndegd.c \
+rndunix.c \
+rndw32.c \
+rndw32ce.c \
+jitterentropy-base.c jitterentropy.h jitterentropy-base-user.h
+
+@ENABLE_O_FLAG_MUNGING_FALSE@o_flag_munging = cat
+
+# The rndjent module needs to be compiled without optimization. */
+@ENABLE_O_FLAG_MUNGING_TRUE@o_flag_munging = sed -e 's/-O\([1-9sg][1-9sg]*\)/-O0/g' -e 's/-Ofast/-O0/g'
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu random/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu random/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+librandom.la: $(librandom_la_OBJECTS) $(librandom_la_DEPENDENCIES) $(EXTRA_librandom_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(librandom_la_OBJECTS) $(librandom_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jitterentropy-base.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-csprng.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-daemon.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-drbg.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-system.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndegd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndhw.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndjent.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndlinux.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndunix.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndw32.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndw32ce.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/jitterentropy-base.Plo
+ -rm -f ./$(DEPDIR)/random-csprng.Plo
+ -rm -f ./$(DEPDIR)/random-daemon.Plo
+ -rm -f ./$(DEPDIR)/random-drbg.Plo
+ -rm -f ./$(DEPDIR)/random-system.Plo
+ -rm -f ./$(DEPDIR)/random.Plo
+ -rm -f ./$(DEPDIR)/rndegd.Plo
+ -rm -f ./$(DEPDIR)/rndhw.Plo
+ -rm -f ./$(DEPDIR)/rndjent.Plo
+ -rm -f ./$(DEPDIR)/rndlinux.Plo
+ -rm -f ./$(DEPDIR)/rndunix.Plo
+ -rm -f ./$(DEPDIR)/rndw32.Plo
+ -rm -f ./$(DEPDIR)/rndw32ce.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/jitterentropy-base.Plo
+ -rm -f ./$(DEPDIR)/random-csprng.Plo
+ -rm -f ./$(DEPDIR)/random-daemon.Plo
+ -rm -f ./$(DEPDIR)/random-drbg.Plo
+ -rm -f ./$(DEPDIR)/random-system.Plo
+ -rm -f ./$(DEPDIR)/random.Plo
+ -rm -f ./$(DEPDIR)/rndegd.Plo
+ -rm -f ./$(DEPDIR)/rndhw.Plo
+ -rm -f ./$(DEPDIR)/rndjent.Plo
+ -rm -f ./$(DEPDIR)/rndlinux.Plo
+ -rm -f ./$(DEPDIR)/rndunix.Plo
+ -rm -f ./$(DEPDIR)/rndw32.Plo
+ -rm -f ./$(DEPDIR)/rndw32ce.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+rndjent.o: $(srcdir)/rndjent.c jitterentropy-base-user.h \
+ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
+ `echo $(COMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
+
+rndjent.lo: $(srcdir)/rndjent.c jitterentropy-base-user.h \
+ $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
+ `echo $(LTCOMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/comm/third_party/libgcrypt/random/jitterentropy-base-user.h b/comm/third_party/libgcrypt/random/jitterentropy-base-user.h
new file mode 100644
index 0000000000..8a8dbd5581
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/jitterentropy-base-user.h
@@ -0,0 +1,134 @@
+/*
+ * Non-physical true random number generator based on timing jitter.
+ *
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2013
+ *
+ * License
+ * =======
+ *
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef GCRYPT_JITTERENTROPY_BASE_USER_H
+#define GCRYPT_JITTERENTROPY_BASE_USER_H
+
+/*
+ * This is Libgcrypt specific platform dependent code. We use a
+ * separate file because jitterentropy.h expects such a file.
+ */
+
+#ifndef USE_JENT
+# error This file expects to be included from rndjent.c (via jitterentropy.h)
+#endif
+#ifndef HAVE_STDINT_H
+# error This module needs stdint.h - try ./configure --disable-jent-support
+#endif
+
+
+/* When using the libgcrypt secure memory mechanism, all precautions
+ * are taken to protect our state. If the user disables secmem during
+ * runtime, it is his decision and we thus try not to overrule his
+ * decision for less memory protection. */
+#define JENT_CPU_JITTERENTROPY_SECURE_MEMORY 1
+#define jent_zalloc(n) _gcry_calloc_secure (1, (n))
+
+
+static void
+jent_get_nstime(u64 *out)
+{
+#if USE_JENT == JENT_USES_RDTSC
+
+ u32 t_eax, t_edx;
+
+ asm volatile (".byte 0x0f,0x31\n\t"
+ : "=a" (t_eax), "=d" (t_edx)
+ );
+ *out = (((u64)t_edx << 32) | t_eax);
+
+#elif USE_JENT == JENT_USES_GETTIME
+
+ struct timespec tv;
+ u64 tmp;
+
+ /* On Linux we could use CLOCK_MONOTONIC(_RAW), but with
+ * CLOCK_REALTIME we get some nice extra entropy once in a while
+ * from the NTP actions that we want to use as well... though, we do
+ * not rely on that extra little entropy. */
+ if (!clock_gettime (CLOCK_REALTIME, &tv))
+ {
+ tmp = tv.tv_sec;
+ tmp = tmp << 32;
+ tmp = tmp | tv.tv_nsec;
+ }
+ else
+ tmp = 0;
+ *out = tmp;
+
+#elif USE_JENT == JENT_USES_READ_REAL_TIME
+
+ /* clock_gettime() on AIX returns a timer value that increments in
+ * steps of 1000. */
+ u64 tmp = 0;
+
+ timebasestruct_t aixtime;
+ read_real_time (&aixtime, TIMEBASE_SZ);
+ tmp = aixtime.tb_high;
+ tmp = tmp << 32;
+ tmp = tmp | aixtime.tb_low;
+ *out = tmp;
+
+#else
+# error No clock available in jent_get_nstime
+#endif
+}
+
+
+static GPGRT_INLINE void
+jent_zfree (void *ptr, unsigned int len)
+{
+ if (ptr)
+ {
+ wipememory (ptr, len);
+ _gcry_free (ptr);
+ }
+}
+
+
+static GPGRT_INLINE int
+jent_fips_enabled(void)
+{
+ return fips_mode();
+}
+
+
+#endif /* GCRYPT_JITTERENTROPY_BASE_USER_H */
diff --git a/comm/third_party/libgcrypt/random/jitterentropy-base.c b/comm/third_party/libgcrypt/random/jitterentropy-base.c
new file mode 100644
index 0000000000..ba435e1bdb
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/jitterentropy-base.c
@@ -0,0 +1,791 @@
+/*
+ * Non-physical true random number generator based on timing jitter.
+ *
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2017
+ *
+ * Design
+ * ======
+ *
+ * See documentation in doc/ folder.
+ *
+ * Interface
+ * =========
+ *
+ * See documentation in doc/ folder.
+ *
+ * License
+ * =======
+ *
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2 are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#undef _FORTIFY_SOURCE
+#pragma GCC optimize ("O0")
+
+#include "jitterentropy.h"
+
+#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+ /* only check optimization in a compilation for real work */
+ #ifdef __OPTIMIZE__
+ #error "The CPU Jitter random number generator must not be compiled with optimizations. See documentation. Use the compiler switch -O0 for compiling jitterentropy-base.c."
+ #endif
+#endif
+
+#define MAJVERSION 2 /* API / ABI incompatible changes, functional changes that
+ * require consumer to be updated (as long as this number
+ * is zero, the API is not considered stable and can
+ * change without a bump of the major version) */
+#define MINVERSION 1 /* API compatible, ABI may change, functional
+ * enhancements only, consumer can be left unchanged if
+ * enhancements are not considered */
+#define PATCHLEVEL 0 /* API / ABI compatible, no functional changes, no
+ * enhancements, bug fixes only */
+
+/**
+ * jent_version() - Return machine-usable version number of jent library
+ *
+ * The function returns a version number that is monotonic increasing
+ * for newer versions. The version numbers are multiples of 100. For example,
+ * version 1.2.3 is converted to 1020300 -- the last two digits are reserved
+ * for future use.
+ *
+ * The result of this function can be used in comparing the version number
+ * in a calling program if version-specific calls need to be make.
+ *
+ * Return: Version number of kcapi library
+ */
+JENT_PRIVATE_STATIC
+unsigned int jent_version(void)
+{
+ unsigned int version = 0;
+
+ version = MAJVERSION * 1000000;
+ version += MINVERSION * 10000;
+ version += PATCHLEVEL * 100;
+
+ return version;
+}
+
+/**
+ * Update of the loop count used for the next round of
+ * an entropy collection.
+ *
+ * Input:
+ * @ec entropy collector struct -- may be NULL
+ * @bits is the number of low bits of the timer to consider
+ * @min is the number of bits we shift the timer value to the right at
+ * the end to make sure we have a guaranteed minimum value
+ *
+ * @return Newly calculated loop counter
+ */
+static uint64_t jent_loop_shuffle(struct rand_data *ec,
+ unsigned int bits, unsigned int min)
+{
+ uint64_t time = 0;
+ uint64_t shuffle = 0;
+ unsigned int i = 0;
+ unsigned int mask = (1<<bits) - 1;
+
+ jent_get_nstime(&time);
+ /*
+ * Mix the current state of the random number into the shuffle
+ * calculation to balance that shuffle a bit more.
+ */
+ if (ec)
+ time ^= ec->data;
+ /*
+ * We fold the time value as much as possible to ensure that as many
+ * bits of the time stamp are included as possible.
+ */
+ for (i = 0; (DATA_SIZE_BITS / bits) > i; i++) {
+ shuffle ^= time & mask;
+ time = time >> bits;
+ }
+
+ /*
+ * We add a lower boundary value to ensure we have a minimum
+ * RNG loop count.
+ */
+ return (shuffle + (1<<min));
+}
+
+/***************************************************************************
+ * Noise sources
+ ***************************************************************************/
+
+/**
+ * CPU Jitter noise source -- this is the noise source based on the CPU
+ * execution time jitter
+ *
+ * This function injects the individual bits of the time value into the
+ * entropy pool using an LFSR.
+ *
+ * The code is deliberately inefficient with respect to the bit shifting
+ * and shall stay that way. This function is the root cause why the code
+ * shall be compiled without optimization. This function not only acts as
+ * folding operation, but this function's execution is used to measure
+ * the CPU execution time jitter. Any change to the loop in this function
+ * implies that careful retesting must be done.
+ *
+ * Input:
+ * @ec entropy collector struct -- may be NULL
+ * @time time stamp to be injected
+ * @loop_cnt if a value not equal to 0 is set, use the given value as number of
+ * loops to perform the folding
+ *
+ * Output:
+ * updated ec->data
+ *
+ * @return Number of loops the folding operation is performed
+ */
+static uint64_t jent_lfsr_time(struct rand_data *ec, uint64_t time,
+ uint64_t loop_cnt)
+{
+ unsigned int i;
+ uint64_t j = 0;
+ uint64_t new = 0;
+#define MAX_FOLD_LOOP_BIT 4
+#define MIN_FOLD_LOOP_BIT 0
+ uint64_t fold_loop_cnt =
+ jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT);
+
+ /*
+ * testing purposes -- allow test app to set the counter, not
+ * needed during runtime
+ */
+ if (loop_cnt)
+ fold_loop_cnt = loop_cnt;
+ for (j = 0; j < fold_loop_cnt; j++) {
+ new = ec->data;
+ for (i = 1; (DATA_SIZE_BITS) >= i; i++) {
+ uint64_t tmp = time << (DATA_SIZE_BITS - i);
+
+ tmp = tmp >> (DATA_SIZE_BITS - 1);
+
+ /*
+ * Fibonacci LSFR with polynomial of
+ * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
+ * primitive according to
+ * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
+ * (the shift values are the polynomial values minus one
+ * due to counting bits from 0 to 63). As the current
+ * position is always the LSB, the polynomial only needs
+ * to shift data in from the left without wrap.
+ */
+ new ^= tmp;
+ new ^= ((new >> 63) & 1);
+ new ^= ((new >> 60) & 1);
+ new ^= ((new >> 55) & 1);
+ new ^= ((new >> 30) & 1);
+ new ^= ((new >> 27) & 1);
+ new ^= ((new >> 22) & 1);
+ new = rol64(new, 1);
+ }
+ }
+ ec->data = new;
+
+ return fold_loop_cnt;
+}
+
+/**
+ * Memory Access noise source -- this is a noise source based on variations in
+ * memory access times
+ *
+ * This function performs memory accesses which will add to the timing
+ * variations due to an unknown amount of CPU wait states that need to be
+ * added when accessing memory. The memory size should be larger than the L1
+ * caches as outlined in the documentation and the associated testing.
+ *
+ * The L1 cache has a very high bandwidth, albeit its access rate is usually
+ * slower than accessing CPU registers. Therefore, L1 accesses only add minimal
+ * variations as the CPU has hardly to wait. Starting with L2, significant
+ * variations are added because L2 typically does not belong to the CPU any more
+ * and therefore a wider range of CPU wait states is necessary for accesses.
+ * L3 and real memory accesses have even a wider range of wait states. However,
+ * to reliably access either L3 or memory, the ec->mem memory must be quite
+ * large which is usually not desirable.
+ *
+ * Input:
+ * @ec Reference to the entropy collector with the memory access data -- if
+ * the reference to the memory block to be accessed is NULL, this noise
+ * source is disabled
+ * @loop_cnt if a value not equal to 0 is set, use the given value as number of
+ * loops to perform the folding
+ *
+ * @return Number of memory access operations
+ */
+static unsigned int jent_memaccess(struct rand_data *ec, uint64_t loop_cnt)
+{
+ unsigned int wrap = 0;
+ uint64_t i = 0;
+#define MAX_ACC_LOOP_BIT 7
+#define MIN_ACC_LOOP_BIT 0
+ uint64_t acc_loop_cnt =
+ jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
+
+ if (NULL == ec || NULL == ec->mem)
+ return 0;
+ wrap = ec->memblocksize * ec->memblocks;
+
+ /*
+ * testing purposes -- allow test app to set the counter, not
+ * needed during runtime
+ */
+ if (loop_cnt)
+ acc_loop_cnt = loop_cnt;
+
+ for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
+ unsigned char *tmpval = ec->mem + ec->memlocation;
+ /*
+ * memory access: just add 1 to one byte,
+ * wrap at 255 -- memory access implies read
+ * from and write to memory location
+ */
+ *tmpval = (*tmpval + 1) & 0xff;
+ /*
+ * Addition of memblocksize - 1 to pointer
+ * with wrap around logic to ensure that every
+ * memory location is hit evenly
+ */
+ ec->memlocation = ec->memlocation + ec->memblocksize - 1;
+ ec->memlocation = ec->memlocation % wrap;
+ }
+ return i;
+}
+
+/***************************************************************************
+ * Start of entropy processing logic
+ ***************************************************************************/
+
+/**
+ * Stuck test by checking the:
+ * 1st derivation of the jitter measurement (time delta)
+ * 2nd derivation of the jitter measurement (delta of time deltas)
+ * 3rd derivation of the jitter measurement (delta of delta of time deltas)
+ *
+ * All values must always be non-zero.
+ *
+ * Input:
+ * @ec Reference to entropy collector
+ * @current_delta Jitter time delta
+ *
+ * @return
+ * 0 jitter measurement not stuck (good bit)
+ * 1 jitter measurement stuck (reject bit)
+ */
+static int jent_stuck(struct rand_data *ec, uint64_t current_delta)
+{
+ int64_t delta2 = ec->last_delta - current_delta;
+ int64_t delta3 = (uint64_t)delta2 - (uint64_t)ec->last_delta2;
+
+ ec->last_delta = current_delta;
+ ec->last_delta2 = delta2;
+
+ if (!current_delta || !delta2 || !delta3)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * This is the heart of the entropy generation: calculate time deltas and
+ * use the CPU jitter in the time deltas. The jitter is injected into the
+ * entropy pool.
+ *
+ * WARNING: ensure that ->prev_time is primed before using the output
+ * of this function! This can be done by calling this function
+ * and not using its result.
+ *
+ * Input:
+ * @entropy_collector Reference to entropy collector
+ *
+ * @return: result of stuck test
+ */
+static int jent_measure_jitter(struct rand_data *ec)
+{
+ uint64_t time = 0;
+ uint64_t current_delta = 0;
+ int stuck;
+
+ /* Invoke one noise source before time measurement to add variations */
+ jent_memaccess(ec, 0);
+
+ /*
+ * Get time stamp and calculate time delta to previous
+ * invocation to measure the timing variations
+ */
+ jent_get_nstime(&time);
+ current_delta = time - ec->prev_time;
+ ec->prev_time = time;
+
+ /* Now call the next noise sources which also injects the data */
+ jent_lfsr_time(ec, current_delta, 0);
+
+ /* Check whether we have a stuck measurement. */
+ stuck = jent_stuck(ec, current_delta);
+
+ /*
+ * Rotate the data buffer by a prime number (any odd number would
+ * do) to ensure that every bit position of the input time stamp
+ * has an even chance of being merged with a bit position in the
+ * entropy pool. We do not use one here as the adjacent bits in
+ * successive time deltas may have some form of dependency. The
+ * chosen value of 7 implies that the low 7 bits of the next
+ * time delta value is concatenated with the current time delta.
+ */
+ if (!stuck)
+ ec->data = rol64(ec->data, 7);
+
+ return stuck;
+}
+
+/**
+ * Shuffle the pool a bit by mixing some value with a bijective function (XOR)
+ * into the pool.
+ *
+ * The function generates a mixer value that depends on the bits set and the
+ * location of the set bits in the random number generated by the entropy
+ * source. Therefore, based on the generated random number, this mixer value
+ * can have 2**64 different values. That mixer value is initialized with the
+ * first two SHA-1 constants. After obtaining the mixer value, it is XORed into
+ * the random number.
+ *
+ * The mixer value is not assumed to contain any entropy. But due to the XOR
+ * operation, it can also not destroy any entropy present in the entropy pool.
+ *
+ * Input:
+ * @entropy_collector Reference to entropy collector
+ */
+static void jent_stir_pool(struct rand_data *entropy_collector)
+{
+ /*
+ * to shut up GCC on 32 bit, we have to initialize the 64 variable
+ * with two 32 bit variables
+ */
+ union c {
+ uint64_t uint64;
+ uint32_t uint32[2];
+ };
+ /*
+ * This constant is derived from the first two 32 bit initialization
+ * vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1
+ */
+ union c constant;
+ /*
+ * The start value of the mixer variable is derived from the third
+ * and fourth 32 bit initialization vector of SHA-1 as defined in
+ * FIPS 180-4 section 5.3.1
+ */
+ union c mixer;
+ unsigned int i = 0;
+
+ /* Ensure that the function implements a constant time operation. */
+ union c throw_away;
+
+ /*
+ * Store the SHA-1 constants in reverse order to make up the 64 bit
+ * value -- this applies to a little endian system, on a big endian
+ * system, it reverses as expected. But this really does not matter
+ * as we do not rely on the specific numbers. We just pick the SHA-1
+ * constants as they have a good mix of bit set and unset.
+ */
+ constant.uint32[1] = 0x67452301;
+ constant.uint32[0] = 0xefcdab89;
+ mixer.uint32[1] = 0x98badcfe;
+ mixer.uint32[0] = 0x10325476;
+
+ for (i = 0; i < DATA_SIZE_BITS; i++) {
+ /*
+ * get the i-th bit of the input random number and only XOR
+ * the constant into the mixer value when that bit is set
+ */
+ if ((entropy_collector->data >> i) & 1)
+ mixer.uint64 ^= constant.uint64;
+ else
+ throw_away.uint64 ^= constant.uint64;
+ mixer.uint64 = rol64(mixer.uint64, 1);
+ }
+ entropy_collector->data ^= mixer.uint64;
+}
+
+/**
+ * Generator of one 64 bit random number
+ * Function fills rand_data->data
+ *
+ * Input:
+ * @ec Reference to entropy collector
+ */
+static void jent_gen_entropy(struct rand_data *ec)
+{
+ unsigned int k = 0;
+
+ /* priming of the ->prev_time value */
+ jent_measure_jitter(ec);
+
+ while (1) {
+ /* If a stuck measurement is received, repeat measurement */
+ if (jent_measure_jitter(ec))
+ continue;
+
+ /*
+ * We multiply the loop value with ->osr to obtain the
+ * oversampling rate requested by the caller
+ */
+ if (++k >= (DATA_SIZE_BITS * ec->osr))
+ break;
+ }
+ if (ec->stir)
+ jent_stir_pool(ec);
+}
+
+/**
+ * The continuous test required by FIPS 140-2 -- the function automatically
+ * primes the test if needed.
+ *
+ * Return:
+ * 0 if FIPS test passed
+ * < 0 if FIPS test failed
+ */
+static int jent_fips_test(struct rand_data *ec)
+{
+ if (ec->fips_enabled == -1)
+ return 0;
+
+ if (ec->fips_enabled == 0) {
+ if (!jent_fips_enabled()) {
+ ec->fips_enabled = -1;
+ return 0;
+ } else
+ ec->fips_enabled = 1;
+ }
+
+ /* prime the FIPS test */
+ if (!ec->old_data) {
+ ec->old_data = ec->data;
+ jent_gen_entropy(ec);
+ }
+
+ if (ec->data == ec->old_data)
+ return -1;
+
+ ec->old_data = ec->data;
+
+ return 0;
+}
+
+/**
+ * Entry function: Obtain entropy for the caller.
+ *
+ * This function invokes the entropy gathering logic as often to generate
+ * as many bytes as requested by the caller. The entropy gathering logic
+ * creates 64 bit per invocation.
+ *
+ * This function truncates the last 64 bit entropy value output to the exact
+ * size specified by the caller.
+ *
+ * Input:
+ * @ec Reference to entropy collector
+ * @data pointer to buffer for storing random data -- buffer must already
+ * exist
+ * @len size of the buffer, specifying also the requested number of random
+ * in bytes
+ *
+ * @return number of bytes returned when request is fulfilled or an error
+ *
+ * The following error codes can occur:
+ * -1 entropy_collector is NULL
+ * -2 FIPS test failed
+ */
+JENT_PRIVATE_STATIC
+ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len)
+{
+ char *p = data;
+ size_t orig_len = len;
+
+ if (NULL == ec)
+ return -1;
+
+ while (0 < len) {
+ size_t tocopy;
+
+ jent_gen_entropy(ec);
+ if (jent_fips_test(ec))
+ return -2;
+
+ if ((DATA_SIZE_BITS / 8) < len)
+ tocopy = (DATA_SIZE_BITS / 8);
+ else
+ tocopy = len;
+ memcpy(p, &ec->data, tocopy);
+
+ len -= tocopy;
+ p += tocopy;
+ }
+
+ /*
+ * To be on the safe side, we generate one more round of entropy
+ * which we do not give out to the caller. That round shall ensure
+ * that in case the calling application crashes, memory dumps, pages
+ * out, or due to the CPU Jitter RNG lingering in memory for long
+ * time without being moved and an attacker cracks the application,
+ * all he reads in the entropy pool is a value that is NEVER EVER
+ * being used for anything. Thus, he does NOT see the previous value
+ * that was returned to the caller for cryptographic purposes.
+ */
+ /*
+ * If we use secured memory, do not use that precaution as the secure
+ * memory protects the entropy pool. Moreover, note that using this
+ * call reduces the speed of the RNG by up to half
+ */
+#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY
+ jent_gen_entropy(ec);
+#endif
+ return orig_len;
+}
+
+/***************************************************************************
+ * Initialization logic
+ ***************************************************************************/
+
+JENT_PRIVATE_STATIC
+struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+ unsigned int flags)
+{
+ struct rand_data *entropy_collector;
+
+ entropy_collector = jent_zalloc(sizeof(struct rand_data));
+ if (NULL == entropy_collector)
+ return NULL;
+
+ if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) {
+ /* Allocate memory for adding variations based on memory
+ * access
+ */
+ entropy_collector->mem =
+ (unsigned char *)jent_zalloc(JENT_MEMORY_SIZE);
+ if (NULL == entropy_collector->mem) {
+ jent_zfree(entropy_collector, sizeof(struct rand_data));
+ return NULL;
+ }
+ entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
+ entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
+ entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
+ }
+
+ /* verify and set the oversampling rate */
+ if (0 == osr)
+ osr = 1; /* minimum sampling rate is 1 */
+ entropy_collector->osr = osr;
+
+ entropy_collector->stir = 1;
+ if (flags & JENT_DISABLE_STIR)
+ entropy_collector->stir = 0;
+ if (flags & JENT_DISABLE_UNBIAS)
+ entropy_collector->disable_unbias = 1;
+
+ /* fill the data pad with non-zero values */
+ jent_gen_entropy(entropy_collector);
+
+ return entropy_collector;
+}
+
+JENT_PRIVATE_STATIC
+void jent_entropy_collector_free(struct rand_data *entropy_collector)
+{
+ if (NULL != entropy_collector) {
+ if (NULL != entropy_collector->mem) {
+ jent_zfree(entropy_collector->mem, JENT_MEMORY_SIZE);
+ entropy_collector->mem = NULL;
+ }
+ jent_zfree(entropy_collector, sizeof(struct rand_data));
+ }
+}
+
+JENT_PRIVATE_STATIC
+int jent_entropy_init(void)
+{
+ int i;
+ uint64_t delta_sum = 0;
+ uint64_t old_delta = 0;
+ int time_backwards = 0;
+ int count_mod = 0;
+ int count_stuck = 0;
+ struct rand_data ec;
+
+ memset(&ec, 0, sizeof(ec));
+
+ /* We could perform statistical tests here, but the problem is
+ * that we only have a few loop counts to do testing. These
+ * loop counts may show some slight skew and we produce
+ * false positives.
+ *
+ * Moreover, only old systems show potentially problematic
+ * jitter entropy that could potentially be caught here. But
+ * the RNG is intended for hardware that is available or widely
+ * used, but not old systems that are long out of favor. Thus,
+ * no statistical tests.
+ */
+
+ /*
+ * We could add a check for system capabilities such as clock_getres or
+ * check for CONFIG_X86_TSC, but it does not make much sense as the
+ * following sanity checks verify that we have a high-resolution
+ * timer.
+ */
+ /*
+ * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
+ * definitely too little.
+ */
+#define TESTLOOPCOUNT 300
+#define CLEARCACHE 100
+ for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
+ uint64_t time = 0;
+ uint64_t time2 = 0;
+ uint64_t delta = 0;
+ unsigned int lowdelta = 0;
+ int stuck;
+
+ /* Invoke core entropy collection logic */
+ jent_get_nstime(&time);
+ ec.prev_time = time;
+ jent_lfsr_time(&ec, time, 0);
+ jent_get_nstime(&time2);
+
+ /* test whether timer works */
+ if (!time || !time2)
+ return ENOTIME;
+ delta = time2 - time;
+ /*
+ * test whether timer is fine grained enough to provide
+ * delta even when called shortly after each other -- this
+ * implies that we also have a high resolution timer
+ */
+ if (!delta)
+ return ECOARSETIME;
+
+ stuck = jent_stuck(&ec, delta);
+
+ /*
+ * up to here we did not modify any variable that will be
+ * evaluated later, but we already performed some work. Thus we
+ * already have had an impact on the caches, branch prediction,
+ * etc. with the goal to clear it to get the worst case
+ * measurements.
+ */
+ if (CLEARCACHE > i)
+ continue;
+
+ if (stuck)
+ count_stuck++;
+
+ /* test whether we have an increasing timer */
+ if (!(time2 > time))
+ time_backwards++;
+
+ /* use 32 bit value to ensure compilation on 32 bit arches */
+ lowdelta = time2 - time;
+ if (!(lowdelta % 100))
+ count_mod++;
+
+ /*
+ * ensure that we have a varying delta timer which is necessary
+ * for the calculation of entropy -- perform this check
+ * only after the first loop is executed as we need to prime
+ * the old_data value
+ */
+ if (delta > old_delta)
+ delta_sum += (delta - old_delta);
+ else
+ delta_sum += (old_delta - delta);
+ old_delta = delta;
+ }
+
+ /*
+ * we allow up to three times the time running backwards.
+ * CLOCK_REALTIME is affected by adjtime and NTP operations. Thus,
+ * if such an operation just happens to interfere with our test, it
+ * should not fail. The value of 3 should cover the NTP case being
+ * performed during our test run.
+ */
+ if (3 < time_backwards)
+ return ENOMONOTONIC;
+
+ /*
+ * Variations of deltas of time must on average be larger
+ * than 1 to ensure the entropy estimation
+ * implied with 1 is preserved
+ */
+ if ((delta_sum) <= 1)
+ return EMINVARVAR;
+
+ /*
+ * Ensure that we have variations in the time stamp below 10 for at least
+ * 10% of all checks -- on some platforms, the counter increments in
+ * multiples of 100, but not always
+ */
+ if ((TESTLOOPCOUNT/10 * 9) < count_mod)
+ return ECOARSETIME;
+
+ /*
+ * If we have more than 90% stuck results, then this Jitter RNG is
+ * likely to not work well.
+ */
+ if (JENT_STUCK_INIT_THRES(TESTLOOPCOUNT) < count_stuck)
+ return ESTUCK;
+
+ return 0;
+}
+
+/***************************************************************************
+ * Statistical test logic not compiled for regular operation
+ ***************************************************************************/
+
+#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+/*
+ * Statistical test: return the time duration for the folding operation. If min
+ * is set, perform the given number of LFSR ops. Otherwise, allow the
+ * loop count shuffling to define the number of LFSR ops.
+ */
+JENT_PRIVATE_STATIC
+uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min)
+{
+ uint64_t time = 0;
+ uint64_t time2 = 0;
+
+ jent_get_nstime(&time);
+ jent_memaccess(ec, min);
+ jent_lfsr_time(ec, time, min);
+ jent_get_nstime(&time2);
+ return ((time2 - time));
+}
+#endif /* CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT */
diff --git a/comm/third_party/libgcrypt/random/jitterentropy.h b/comm/third_party/libgcrypt/random/jitterentropy.h
new file mode 100644
index 0000000000..3b7d14a18e
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/jitterentropy.h
@@ -0,0 +1,148 @@
+/*
+ * Non-physical true random number generator based on timing jitter.
+ *
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ *
+ * License
+ * =======
+ *
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _JITTERENTROPY_H
+#define _JITTERENTROPY_H
+
+#ifdef __KERNEL__
+#include "jitterentropy-base-kernel.h"
+#else
+#include "jitterentropy-base-user.h"
+#endif /* __KERNEL__ */
+
+/* The entropy pool */
+struct rand_data
+{
+ /* all data values that are vital to maintain the security
+ * of the RNG are marked as SENSITIVE. A user must not
+ * access that information while the RNG executes its loops to
+ * calculate the next random value. */
+ uint64_t data; /* SENSITIVE Actual random number */
+ uint64_t old_data; /* SENSITIVE Previous random number */
+ uint64_t prev_time; /* SENSITIVE Previous time stamp */
+#define DATA_SIZE_BITS ((sizeof(uint64_t)) * 8)
+ uint64_t last_delta; /* SENSITIVE stuck test */
+ int64_t last_delta2; /* SENSITIVE stuck test */
+ unsigned int osr; /* Oversample rate */
+ int fips_enabled; /* FIPS enabled? */
+ unsigned int stir:1; /* Post-processing stirring */
+ unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */
+#define JENT_MEMORY_BLOCKS 64
+#define JENT_MEMORY_BLOCKSIZE 32
+#define JENT_MEMORY_ACCESSLOOPS 128
+#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
+ unsigned char *mem; /* Memory access location with size of
+ * memblocks * memblocksize */
+ unsigned int memlocation; /* Pointer to byte in *mem */
+ unsigned int memblocks; /* Number of memory blocks in *mem */
+ unsigned int memblocksize; /* Size of one memory block in bytes */
+ unsigned int memaccessloops; /* Number of memory accesses per random
+ * bit generation */
+};
+
+/* Flags that can be used to initialize the RNG */
+#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */
+#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */
+#define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
+ entropy, saves MEMORY_SIZE RAM for
+ entropy collector */
+
+/* -- BEGIN Main interface functions -- */
+
+#ifndef JENT_STUCK_INIT_THRES
+/*
+ * Per default, not more than 90% of all measurements during initialization
+ * are allowed to be stuck.
+ *
+ * It is allowed to change this value as required for the intended environment.
+ */
+#define JENT_STUCK_INIT_THRES(x) (x/10 * 9)
+#endif
+
+#ifdef JENT_PRIVATE_COMPILE
+# define JENT_PRIVATE_STATIC static
+#else /* JENT_PRIVATE_COMPILE */
+# define JENT_PRIVATE_STATIC
+#endif
+
+/* Number of low bits of the time value that we want to consider */
+/* get raw entropy */
+JENT_PRIVATE_STATIC
+ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len);
+/* initialize an instance of the entropy collector */
+JENT_PRIVATE_STATIC
+struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+ unsigned int flags);
+/* clearing of entropy collector */
+JENT_PRIVATE_STATIC
+void jent_entropy_collector_free(struct rand_data *entropy_collector);
+
+/* initialization of entropy collector */
+JENT_PRIVATE_STATIC
+int jent_entropy_init(void);
+
+/* return version number of core library */
+JENT_PRIVATE_STATIC
+unsigned int jent_version(void);
+
+/* -- END of Main interface functions -- */
+
+/* -- BEGIN error codes for init function -- */
+#define ENOTIME 1 /* Timer service not available */
+#define ECOARSETIME 2 /* Timer too coarse for RNG */
+#define ENOMONOTONIC 3 /* Timer is not monotonic increasing */
+#define EMINVARIATION 4 /* Timer variations too small for RNG */
+#define EVARVAR 5 /* Timer does not produce variations of variations
+ (2nd derivation of time is zero) */
+#define EMINVARVAR 6 /* Timer variations of variations is too small */
+#define EPROGERR 7 /* Programming error */
+#define ESTUCK 8 /* Too many stuck results during init. */
+
+/* -- BEGIN statistical test functions only complied with CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT -- */
+
+#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+JENT_PRIVATE_STATIC
+uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min);
+#endif /* CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT */
+
+/* -- END of statistical test function -- */
+
+#endif /* _JITTERENTROPY_H */
diff --git a/comm/third_party/libgcrypt/random/rand-internal.h b/comm/third_party/libgcrypt/random/rand-internal.h
new file mode 100644
index 0000000000..3422156957
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rand-internal.h
@@ -0,0 +1,148 @@
+/* rand-internal.h - header to glue the random functions
+ * Copyright (C) 1998, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef G10_RAND_INTERNAL_H
+#define G10_RAND_INTERNAL_H
+
+#include "../src/cipher-proto.h"
+
+/* Constants used to define the origin of random added to the pool.
+ The code is sensitive to the order of the values. */
+enum random_origins
+ {
+ RANDOM_ORIGIN_INIT = 0, /* Used only for initialization. */
+ RANDOM_ORIGIN_EXTERNAL = 1, /* Added from an external source. */
+ RANDOM_ORIGIN_FASTPOLL = 2, /* Fast random poll function. */
+ RANDOM_ORIGIN_SLOWPOLL = 3, /* Slow poll function. */
+ RANDOM_ORIGIN_EXTRAPOLL = 4 /* Used to mark an extra pool seed
+ due to a GCRY_VERY_STRONG_RANDOM
+ random request. */
+ };
+
+#define RANDOM_CONF_DISABLE_JENT 1
+#define RANDOM_CONF_ONLY_URANDOM 2
+
+
+/*-- random.c --*/
+unsigned int _gcry_random_read_conf (void);
+void _gcry_random_progress (const char *what, int printchar,
+ int current, int total);
+
+
+/*-- random-csprng.c --*/
+void _gcry_rngcsprng_initialize (int full);
+void _gcry_rngcsprng_close_fds (void);
+void _gcry_rngcsprng_dump_stats (void);
+void _gcry_rngcsprng_secure_alloc (void);
+void _gcry_rngcsprng_enable_quick_gen (void);
+void _gcry_rngcsprng_set_daemon_socket (const char *socketname);
+int _gcry_rngcsprng_use_daemon (int onoff);
+int _gcry_rngcsprng_is_faked (void);
+gcry_error_t _gcry_rngcsprng_add_bytes (const void *buf, size_t buflen,
+ int quality);
+void *_gcry_rngcsprng_get_bytes (size_t nbytes,
+ enum gcry_random_level level);
+void *_gcry_rngcsprng_get_bytes_secure (size_t nbytes,
+ enum gcry_random_level level);
+void _gcry_rngcsprng_randomize (void *buffer, size_t length,
+ enum gcry_random_level level);
+void _gcry_rngcsprng_set_seed_file (const char *name);
+void _gcry_rngcsprng_update_seed_file (void);
+void _gcry_rngcsprng_fast_poll (void);
+
+/*-- random-drbg.c --*/
+void _gcry_rngdrbg_inititialize (int full);
+void _gcry_rngdrbg_close_fds (void);
+void _gcry_rngdrbg_dump_stats (void);
+int _gcry_rngdrbg_is_faked (void);
+gcry_error_t _gcry_rngdrbg_add_bytes (const void *buf, size_t buflen,
+ int quality);
+void _gcry_rngdrbg_randomize (void *buffer, size_t length,
+ enum gcry_random_level level);
+gcry_error_t _gcry_rngdrbg_selftest (selftest_report_func_t report);
+
+/*-- random-system.c --*/
+void _gcry_rngsystem_initialize (int full);
+void _gcry_rngsystem_close_fds (void);
+void _gcry_rngsystem_dump_stats (void);
+int _gcry_rngsystem_is_faked (void);
+gcry_error_t _gcry_rngsystem_add_bytes (const void *buf, size_t buflen,
+ int quality);
+void _gcry_rngsystem_randomize (void *buffer, size_t length,
+ enum gcry_random_level level);
+
+
+
+/*-- rndlinux.c --*/
+int _gcry_rndlinux_gather_random (void (*add) (const void *, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level);
+
+/*-- rndunix.c --*/
+int _gcry_rndunix_gather_random (void (*add) (const void *, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level);
+
+/*-- rndegd.c --*/
+int _gcry_rndegd_gather_random (void (*add) (const void *, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level);
+int _gcry_rndegd_connect_socket (int nofail);
+
+/*-- rndw32.c --*/
+int _gcry_rndw32_gather_random (void (*add) (const void *, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level);
+void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin );
+
+/*-- rndw32ce.c --*/
+int _gcry_rndw32ce_gather_random (void (*add) (const void *, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level);
+void _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin );
+
+/*-- rndjent.c --*/
+size_t _gcry_rndjent_poll (void (*add)(const void*,
+ size_t, enum random_origins),
+ enum random_origins origin,
+ size_t length);
+void _gcry_rndjent_dump_stats (void);
+void _gcry_rndjent_fini (void);
+
+/*-- rndhw.c --*/
+int _gcry_rndhw_failed_p (void);
+void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin);
+size_t _gcry_rndhw_poll_slow (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin, size_t req_length);
+
+
+
+#endif /*G10_RAND_INTERNAL_H*/
diff --git a/comm/third_party/libgcrypt/random/random-csprng.c b/comm/third_party/libgcrypt/random/random-csprng.c
new file mode 100644
index 0000000000..66f5786499
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/random-csprng.c
@@ -0,0 +1,1367 @@
+/* random-csprng.c - CSPRNG style random number generator (libgcrypt classic)
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ * 2007, 2008, 2010, 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ This random number generator is modelled after the one described in
+ Peter Gutmann's 1998 Usenix Security Symposium paper: "Software
+ Generation of Practically Strong Random Numbers". See also chapter
+ 6 in his book "Cryptographic Security Architecture", New York,
+ 2004, ISBN 0-387-95387-6.
+
+ Note that the acronym CSPRNG stands for "Continuously Seeded
+ PseudoRandom Number Generator" as used in Peter's implementation of
+ the paper and not only for "Cryptographically Secure PseudoRandom
+ Number Generator".
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_GETHRTIME
+#include <sys/times.h>
+#endif
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+#ifdef HAVE_GETRUSAGE
+#include <sys/resource.h>
+#endif
+#ifdef __MINGW32__
+#include <process.h>
+#endif
+#include "g10lib.h"
+#include "random.h"
+#include "rand-internal.h"
+#include "cipher.h" /* _gcry_sha1_hash_buffer */
+#include "../cipher/sha1.h" /* _gcry_sha1_mixblock */
+
+#ifndef RAND_MAX /* For SunOS. */
+#define RAND_MAX 32767
+#endif
+
+/* Check whether we can lock the seed file read write. */
+#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM)
+#define LOCK_SEED_FILE 1
+#else
+#define LOCK_SEED_FILE 0
+#endif
+
+/* Define the constant we use for transforming the pool at read-out. */
+#if SIZEOF_UNSIGNED_LONG == 8
+#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
+#elif SIZEOF_UNSIGNED_LONG == 4
+#define ADD_VALUE 0xa5a5a5a5
+#else
+#error weird size for an unsigned long
+#endif
+
+/* Contstants pertaining to the hash pool. */
+#define BLOCKLEN 64 /* Hash this amount of bytes... */
+#define DIGESTLEN 20 /* ... into a digest of this length (sha-1). */
+/* POOLBLOCKS is the number of digests which make up the pool. */
+#define POOLBLOCKS 30
+/* POOLSIZE must be a multiple of the digest length to make the AND
+ operations faster, the size should also be a multiple of unsigned
+ long. */
+#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
+#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
+#error Please make sure that poolsize is a multiple of unsigned long
+#endif
+#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
+
+
+/* RNDPOOL is the pool we use to collect the entropy and to stir it
+ up. Its allocated size is POOLSIZE+BLOCKLEN. Note that this is
+ also an indication on whether the module has been fully
+ initialized. */
+static unsigned char *rndpool;
+
+/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL.
+ Its allocated size is also POOLSIZE+BLOCKLEN. */
+static unsigned char *keypool;
+
+/* This is the offset into RNDPOOL where the next random bytes are to
+ be mixed in. */
+static size_t pool_writepos;
+
+/* When reading data out of KEYPOOL, we start the read at different
+ positions. This variable keeps track on where to read next. */
+static size_t pool_readpos;
+
+/* This flag is set to true as soon as the pool has been completely
+ filled the first time. This may happen either by reading a seed
+ file or by adding enough entropy. */
+static int pool_filled;
+
+/* This counter is used to track whether the initial seeding has been
+ done with enough bytes from a reliable entropy source. */
+static size_t pool_filled_counter;
+
+/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
+ have stricter requirements on what kind of entropy is in the pool.
+ In particular POOL_FILLED is not sufficient. Thus we add some
+ extra seeding and set this flag to true if the extra seeding has
+ been done. */
+static int did_initial_extra_seeding;
+
+/* This variable is used to estimated the amount of fresh entropy
+ available in RNDPOOL. */
+static int pool_balance;
+
+/* After a mixing operation this variable will be set to true and
+ cleared if new entropy has been added or a remix is required for
+ other reasons. */
+static int just_mixed;
+
+/* The name of the seed file or NULL if no seed file has been defined.
+ The seed file needs to be registered at initialization time. We
+ keep a malloced copy here. */
+static char *seed_file_name;
+
+/* If a seed file has been registered and maybe updated on exit this
+ flag set. */
+static int allow_seed_file_update;
+
+/* Option flag set at initialiation time to force allocation of the
+ pool in secure memory. */
+static int secure_alloc;
+
+/* This function pointer is set to the actual entropy gathering
+ function during initialization. After initialization it is
+ guaranteed to point to function. (On systems without a random
+ gatherer module a dummy function is used).*/
+static int (*slow_gather_fnc)(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins, size_t, int);
+
+/* This function is set to the actual fast entropy gathering function
+ during initialization. If it is NULL, no such function is
+ available. */
+static void (*fast_gather_fnc)(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins);
+
+
+/* Option flag useful for debugging and the test suite. If set
+ requests for very strong random are degraded to strong random. Not
+ used by regular applications. */
+static int quick_test;
+
+/* This is the lock we use to protect all pool operations. */
+GPGRT_LOCK_DEFINE (pool_lock);
+
+/* This is a helper for assert calls. These calls are used to assert
+ that functions are called in a locked state. It is not meant to be
+ thread-safe but as a method to get aware of missing locks in the
+ test suite. */
+static int pool_is_locked;
+
+
+/* We keep some counters in this structure for the sake of the
+ _gcry_random_dump_stats () function. */
+static struct
+{
+ unsigned long mixrnd;
+ unsigned long mixkey;
+ unsigned long slowpolls;
+ unsigned long fastpolls;
+ unsigned long getbytes1;
+ unsigned long ngetbytes1;
+ unsigned long getbytes2;
+ unsigned long ngetbytes2;
+ unsigned long addbytes;
+ unsigned long naddbytes;
+} rndstats;
+
+
+
+/* --- Stuff pertaining to the random daemon support. --- */
+#ifdef USE_RANDOM_DAEMON
+
+/* If ALLOW_DAEMON is true, the module will try to use the random
+ daemon first. If the daemon has failed, this variable is set to
+ back to false and the code continues as normal. Note, we don't
+ test this flag in a locked state because a wrong value does not
+ harm and the trhead will find out itself that the daemon does not
+ work and set it (again) to false. */
+static int allow_daemon;
+
+/* During initialization, the user may set a non-default socket name
+ for accessing the random daemon. If this value is NULL, the
+ default name will be used. */
+static char *daemon_socket_name;
+
+#endif /*USE_RANDOM_DAEMON*/
+
+
+
+/* --- Prototypes --- */
+static void read_pool (byte *buffer, size_t length, int level );
+static void add_randomness (const void *buffer, size_t length,
+ enum random_origins origin);
+static void random_poll (void);
+static void do_fast_random_poll (void);
+static int (*getfnc_gather_random (void))(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins, size_t, int);
+static void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins);
+static void read_random_source (enum random_origins origin,
+ size_t length, int level);
+
+
+
+/* --- Functions --- */
+
+
+/* Basic initialization which is required to initialize mutexes and
+ such. It does not run a full initialization so that the filling of
+ the random pool can be delayed until it is actually needed. We
+ assume that this function is used before any concurrent access
+ happens. */
+static void
+initialize_basics(void)
+{
+ static int initialized;
+
+ if (!initialized)
+ {
+ initialized = 1;
+
+#ifdef USE_RANDOM_DAEMON
+ _gcry_daemon_initialize_basics ();
+#endif /*USE_RANDOM_DAEMON*/
+
+ /* Make sure that we are still using the values we have
+ traditionally used for the random levels. */
+ gcry_assert (GCRY_WEAK_RANDOM == 0
+ && GCRY_STRONG_RANDOM == 1
+ && GCRY_VERY_STRONG_RANDOM == 2);
+ }
+}
+
+/* Take the pool lock. */
+static void
+lock_pool (void)
+{
+ int err;
+
+ err = gpgrt_lock_lock (&pool_lock);
+ if (err)
+ log_fatal ("failed to acquire the pool lock: %s\n", gpg_strerror (err));
+ pool_is_locked = 1;
+}
+
+/* Release the pool lock. */
+static void
+unlock_pool (void)
+{
+ int err;
+
+ pool_is_locked = 0;
+ err = gpgrt_lock_unlock (&pool_lock);
+ if (err)
+ log_fatal ("failed to release the pool lock: %s\n", gpg_strerror (err));
+}
+
+
+/* Full initialization of this module. */
+static void
+initialize(void)
+{
+ /* Although the basic initialization should have happened already,
+ we call it here to make sure that all prerequisites are met. */
+ initialize_basics ();
+
+ /* Now we can look the pool and complete the initialization if
+ necessary. */
+ lock_pool ();
+ if (!rndpool)
+ {
+ /* The data buffer is allocated somewhat larger, so that we can
+ use this extra space (which is allocated in secure memory) as
+ a temporary hash buffer */
+ rndpool = (secure_alloc
+ ? xcalloc_secure (1, POOLSIZE + BLOCKLEN)
+ : xcalloc (1, POOLSIZE + BLOCKLEN));
+ keypool = (secure_alloc
+ ? xcalloc_secure (1, POOLSIZE + BLOCKLEN)
+ : xcalloc (1, POOLSIZE + BLOCKLEN));
+
+ /* Setup the slow entropy gathering function. The code requires
+ that this function exists. */
+ slow_gather_fnc = getfnc_gather_random ();
+
+ /* Setup the fast entropy gathering function. */
+ fast_gather_fnc = getfnc_fast_random_poll ();
+
+ }
+ unlock_pool ();
+}
+
+
+
+
+/* Initialize this random subsystem. If FULL is false, this function
+ merely calls the initialize and does not do anything more. Doing
+ this is not really required but when running in a threaded
+ environment we might get a race condition otherwise. */
+void
+_gcry_rngcsprng_initialize (int full)
+{
+ if (!full)
+ initialize_basics ();
+ else
+ initialize ();
+}
+
+
+/* Try to close the FDs of the random gather module. This is
+ currently only implemented for rndlinux. */
+void
+_gcry_rngcsprng_close_fds (void)
+{
+ lock_pool ();
+#if USE_RNDLINUX
+ _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
+ pool_filled = 0; /* Force re-open on next use. */
+#endif
+ unlock_pool ();
+}
+
+
+void
+_gcry_rngcsprng_dump_stats (void)
+{
+ /* In theory we would need to lock the stats here. However this
+ function is usually called during cleanup and then we _might_ run
+ into problems. */
+
+ log_info ("random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
+ " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n",
+ POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
+ rndstats.naddbytes, rndstats.addbytes,
+ rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
+ rndstats.ngetbytes2, rndstats.getbytes2,
+ _gcry_rndhw_failed_p()? " (hwrng failed)":"");
+}
+
+
+/* This function should be called during initialization and before
+ initialization of this module to place the random pools into secure
+ memory. */
+void
+_gcry_rngcsprng_secure_alloc (void)
+{
+ secure_alloc = 1;
+}
+
+
+/* This may be called before full initialization to degrade the
+ quality of the RNG for the sake of a faster running test suite. */
+void
+_gcry_rngcsprng_enable_quick_gen (void)
+{
+ quick_test = 1;
+}
+
+
+void
+_gcry_rngcsprng_set_daemon_socket (const char *socketname)
+{
+#ifdef USE_RANDOM_DAEMON
+ if (daemon_socket_name)
+ BUG ();
+
+ daemon_socket_name = gcry_xstrdup (socketname);
+#else /*!USE_RANDOM_DAEMON*/
+ (void)socketname;
+#endif /*!USE_RANDOM_DAEMON*/
+}
+
+/* With ONOFF set to 1, enable the use of the daemon. With ONOFF set
+ to 0, disable the use of the daemon. With ONOF set to -1, return
+ whether the daemon has been enabled. */
+int
+_gcry_rngcsprng_use_daemon (int onoff)
+{
+#ifdef USE_RANDOM_DAEMON
+ int last;
+
+ /* This is not really thread safe. However it is expected that this
+ function is being called during initialization and at that point
+ we are for other reasons not really thread safe. We do not want
+ to lock it because we might eventually decide that this function
+ may even be called prior to gcry_check_version. */
+ last = allow_daemon;
+ if (onoff != -1)
+ allow_daemon = onoff;
+
+ return last;
+#else /*!USE_RANDOM_DAEMON*/
+ (void)onoff;
+ return 0;
+#endif /*!USE_RANDOM_DAEMON*/
+}
+
+
+/* This function returns true if no real RNG is available or the
+ quality of the RNG has been degraded for test purposes. */
+int
+_gcry_rngcsprng_is_faked (void)
+{
+ /* We need to initialize due to the runtime determination of
+ available entropy gather modules. */
+ initialize();
+ return quick_test;
+}
+
+
+/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
+ should be in the range of 0..100 to indicate the goodness of the
+ entropy added, or -1 for goodness not known. */
+gcry_error_t
+_gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality)
+{
+ size_t nbytes;
+ const char *bufptr;
+
+ if (quality == -1)
+ quality = 35;
+ else if (quality > 100)
+ quality = 100;
+ else if (quality < 0)
+ quality = 0;
+
+ if (!buf)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (!buflen || quality < 10)
+ return 0; /* Take a shortcut. */
+
+ /* Because we don't increment the entropy estimation with FASTPOLL,
+ we don't need to take lock that estimation while adding from an
+ external source. This limited entropy estimation also means that
+ we can't take QUALITY into account. */
+ initialize_basics ();
+ bufptr = buf;
+ while (buflen)
+ {
+ nbytes = buflen > POOLSIZE? POOLSIZE : buflen;
+ lock_pool ();
+ if (rndpool)
+ add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL);
+ unlock_pool ();
+ bufptr += nbytes;
+ buflen -= nbytes;
+ }
+ return 0;
+}
+
+
+/* Public function to fill the buffer with LENGTH bytes of
+ cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
+ not very strong, GCRY_STRONG_RANDOM is strong enough for most
+ usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
+ may be very slow. */
+void
+_gcry_rngcsprng_randomize (void *buffer, size_t length,
+ enum gcry_random_level level)
+{
+ unsigned char *p;
+
+ /* Make sure we are initialized. */
+ initialize ();
+
+ /* Handle our hack used for regression tests of Libgcrypt. */
+ if ( quick_test && level > GCRY_STRONG_RANDOM )
+ level = GCRY_STRONG_RANDOM;
+
+ /* Make sure the level is okay. */
+ level &= 3;
+
+#ifdef USE_RANDOM_DAEMON
+ if (allow_daemon
+ && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level))
+ return; /* The daemon succeeded. */
+ allow_daemon = 0; /* Daemon failed - switch off. */
+#endif /*USE_RANDOM_DAEMON*/
+
+ /* Acquire the pool lock. */
+ lock_pool ();
+
+ /* Update the statistics. */
+ if (level >= GCRY_VERY_STRONG_RANDOM)
+ {
+ rndstats.getbytes2 += length;
+ rndstats.ngetbytes2++;
+ }
+ else
+ {
+ rndstats.getbytes1 += length;
+ rndstats.ngetbytes1++;
+ }
+
+ /* Read the random into the provided buffer. */
+ for (p = buffer; length > 0;)
+ {
+ size_t n;
+
+ n = length > POOLSIZE? POOLSIZE : length;
+ read_pool (p, n, level);
+ length -= n;
+ p += n;
+ }
+
+ /* Release the pool lock. */
+ unlock_pool ();
+}
+
+
+
+
+/*
+ * Mix the 600 byte pool. Note that the 64 byte scratch area directly
+ * follows the pool. The numbers in the diagram give the number of
+ * bytes.
+ * <................600...............> <.64.>
+ * pool |------------------------------------| |------|
+ * <20><.24.> <20>
+ * | | +-----+
+ * +-----|-------------------------------|-+
+ * +-------------------------------|-|-+
+ * v v v
+ * |------|
+ * <hash>
+ * +---------------------------------------+
+ * v
+ * <20>
+ * pool' |------------------------------------|
+ * <20><20><.24.>
+ * +---|-----|---------------------------+
+ * +-----|---------------------------|-+
+ * +---------------------------|-|-+
+ * v v v
+ * |------|
+ * <hash>
+ * |
+ * +-----------------------------------+
+ * v
+ * <20>
+ * pool'' |------------------------------------|
+ * <20><20><20><.24.>
+ * +---|-----|-----------------------+
+ * +-----|-----------------------|-+
+ * +-----------------------|-|-+
+ * v v v
+ *
+ * and so on until we did this for all 30 blocks.
+ *
+ * To better protect against implementation errors in this code, we
+ * xor a digest of the entire pool into the pool before mixing.
+ *
+ * Note: this function must only be called with a locked pool.
+ */
+static void
+mix_pool(unsigned char *pool)
+{
+ static unsigned char failsafe_digest[DIGESTLEN];
+ static int failsafe_digest_valid;
+
+ unsigned char *hashbuf = pool + POOLSIZE;
+ unsigned char *p, *pend;
+ int i, n;
+ SHA1_CONTEXT md;
+ unsigned int nburn;
+
+#if DIGESTLEN != 20
+#error must have a digest length of 20 for SHA-1
+#endif
+
+ gcry_assert (pool_is_locked);
+ _gcry_sha1_mixblock_init (&md);
+
+ /* pool_0 -> pool'. */
+ pend = pool + POOLSIZE;
+ memcpy (hashbuf, pend - DIGESTLEN, DIGESTLEN);
+ memcpy (hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
+ nburn = _gcry_sha1_mixblock (&md, hashbuf);
+ memcpy (pool, hashbuf, DIGESTLEN);
+
+ if (failsafe_digest_valid && pool == rndpool)
+ {
+ for (i=0; i < DIGESTLEN; i++)
+ pool[i] ^= failsafe_digest[i];
+ }
+
+ /* Loop for the remaining iterations. */
+ p = pool;
+ for (n=1; n < POOLBLOCKS; n++)
+ {
+ if (p + BLOCKLEN < pend)
+ memcpy (hashbuf, p, BLOCKLEN);
+ else
+ {
+ unsigned char *pp = p;
+
+ for (i=0; i < BLOCKLEN; i++ )
+ {
+ if ( pp >= pend )
+ pp = pool;
+ hashbuf[i] = *pp++;
+ }
+ }
+
+ _gcry_sha1_mixblock (&md, hashbuf);
+ p += DIGESTLEN;
+ memcpy (p, hashbuf, DIGESTLEN);
+ }
+
+ /* Our hash implementation does only leave small parts (64 bytes)
+ of the pool on the stack, so it is okay not to require secure
+ memory here. Before we use this pool, it will be copied to the
+ help buffer anyway. */
+ if ( pool == rndpool)
+ {
+ _gcry_sha1_hash_buffer (failsafe_digest, pool, POOLSIZE);
+ failsafe_digest_valid = 1;
+ }
+
+ _gcry_burn_stack (nburn);
+}
+
+
+void
+_gcry_rngcsprng_set_seed_file (const char *name)
+{
+ if (seed_file_name)
+ BUG ();
+ seed_file_name = xstrdup (name);
+}
+
+
+
+/* Helper for my_open.
+ * Return a malloced wide char string from an UTF-8 encoded input
+ * string STRING. Caller must free this value. Returns NULL and sets
+ * ERRNO on failure. Calling this function with STRING set to NULL is
+ * not defined. */
+#ifdef HAVE_W32_SYSTEM
+static wchar_t *
+utf8_to_wchar (const char *string)
+{
+ int n;
+ size_t nbytes;
+ wchar_t *result;
+
+ n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
+ if (n < 0)
+ {
+ gpg_err_set_errno (EINVAL);
+ return NULL;
+ }
+
+ nbytes = (size_t)(n+1) * sizeof(*result);
+ if (nbytes / sizeof(*result) != (n+1))
+ {
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+ result = xtrymalloc (nbytes);
+ if (!result)
+ return NULL;
+
+ n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
+ if (n < 0)
+ {
+ xfree (result);
+ gpg_err_set_errno (EINVAL);
+ result = NULL;
+ }
+ return result;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* Helper for my_open. */
+#ifdef HAVE_W32_SYSTEM
+static int
+any8bitchar (const char *string)
+{
+ if (string)
+ for ( ; *string; string++)
+ if ((*string & 0x80))
+ return 1;
+ return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* A wrapper around open to handle Unicode file names under Windows. */
+static int
+my_open (const char *name, int flags, unsigned int mode)
+{
+#ifdef HAVE_W32_SYSTEM
+ if (any8bitchar (name))
+ {
+ wchar_t *wname;
+ int ret;
+
+ wname = utf8_to_wchar (name);
+ if (!wname)
+ return -1;
+ ret = _wopen (wname, flags, mode);
+ xfree (wname);
+ return ret;
+ }
+ else
+ return open (name, flags, mode);
+#else
+ return open (name, flags, mode);
+#endif
+}
+
+
+/* Lock an open file identified by file descriptor FD and wait a
+ reasonable time to succeed. With FOR_WRITE set to true a write
+ lock will be taken. FNAME is used only for diagnostics. Returns 0
+ on success or -1 on error. */
+static int
+lock_seed_file (int fd, const char *fname, int for_write)
+{
+#ifdef __GCC__
+#warning Check whether we can lock on Windows.
+#endif
+#if LOCK_SEED_FILE
+ struct flock lck;
+ struct timeval tv;
+ int backoff=0;
+
+ /* We take a lock on the entire file. */
+ memset (&lck, 0, sizeof lck);
+ lck.l_type = for_write? F_WRLCK : F_RDLCK;
+ lck.l_whence = SEEK_SET;
+
+ while (fcntl (fd, F_SETLK, &lck) == -1)
+ {
+ if (errno != EAGAIN && errno != EACCES)
+ {
+ log_info (_("can't lock `%s': %s\n"), fname, strerror (errno));
+ return -1;
+ }
+
+ if (backoff > 2) /* Show the first message after ~2.25 seconds. */
+ log_info( _("waiting for lock on `%s'...\n"), fname);
+
+ tv.tv_sec = backoff;
+ tv.tv_usec = 250000;
+ select (0, NULL, NULL, NULL, &tv);
+ if (backoff < 10)
+ backoff++ ;
+ }
+#else
+ (void)fd;
+ (void)fname;
+ (void)for_write;
+#endif /*!LOCK_SEED_FILE*/
+ return 0;
+}
+
+
+/* Read in a seed from the random_seed file and return true if this
+ was successful.
+
+ Note: Multiple instances of applications sharing the same random
+ seed file can be started in parallel, in which case they will read
+ out the same pool and then race for updating it (the last update
+ overwrites earlier updates). They will differentiate only by the
+ weak entropy that is added in read_seed_file based on the PID and
+ clock, and up to 32 bytes from a non-blocking entropy source. The
+ consequence is that the output of these different instances is
+ correlated to some extent. In the perfect scenario, the attacker
+ can control (or at least guess) the PID and clock of the
+ application, and drain the system's entropy pool to reduce the "up
+ to 32 bytes" above to 0. Then the dependencies of the initial
+ states of the pools are completely known. */
+static int
+read_seed_file (void)
+{
+ int fd;
+ struct stat sb;
+ unsigned char buffer[POOLSIZE];
+ int n;
+
+ gcry_assert (pool_is_locked);
+
+ if (!seed_file_name)
+ return 0;
+
+#ifdef HAVE_DOSISH_SYSTEM
+ fd = my_open (seed_file_name, O_RDONLY | O_BINARY, 0);
+#else
+ fd = my_open (seed_file_name, O_RDONLY, 0);
+#endif
+ if( fd == -1 && errno == ENOENT)
+ {
+ allow_seed_file_update = 1;
+ return 0;
+ }
+
+ if (fd == -1 )
+ {
+ log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
+ return 0;
+ }
+ if (lock_seed_file (fd, seed_file_name, 0))
+ {
+ close (fd);
+ return 0;
+ }
+ if (fstat( fd, &sb ) )
+ {
+ log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
+ close(fd);
+ return 0;
+ }
+ if (!S_ISREG(sb.st_mode) )
+ {
+ log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
+ close(fd);
+ return 0;
+ }
+ if (!sb.st_size )
+ {
+ log_info(_("note: random_seed file is empty\n") );
+ close(fd);
+ allow_seed_file_update = 1;
+ return 0;
+ }
+ if (sb.st_size != POOLSIZE )
+ {
+ log_info(_("warning: invalid size of random_seed file - not used\n") );
+ close(fd);
+ return 0;
+ }
+
+ do
+ {
+ n = read( fd, buffer, POOLSIZE );
+ }
+ while (n == -1 && errno == EINTR );
+
+ if (n != POOLSIZE)
+ {
+ log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
+ close(fd);/*NOTREACHED*/
+ return 0;
+ }
+
+ close(fd);
+
+ add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
+ /* add some minor entropy to the pool now (this will also force a mixing) */
+ {
+ pid_t x = getpid();
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+ }
+ {
+ time_t x = time(NULL);
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+ }
+ {
+ clock_t x = clock();
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+ }
+
+ /* And read a few bytes from our entropy source. If we have the
+ * Jitter RNG we can fast get a lot of entropy. Thus we read 1024
+ * bits from that source.
+ *
+ * Without the Jitter RNG we keep the old method of reading only a
+ * few bytes usually from /dev/urandom which won't block. */
+ if (_gcry_rndjent_get_version (NULL))
+ read_random_source (RANDOM_ORIGIN_INIT, 128, GCRY_STRONG_RANDOM);
+ else
+ read_random_source (RANDOM_ORIGIN_INIT, 32, GCRY_STRONG_RANDOM);
+
+ allow_seed_file_update = 1;
+ return 1;
+}
+
+
+void
+_gcry_rngcsprng_update_seed_file (void)
+{
+ unsigned long *sp, *dp;
+ int fd, i;
+
+ /* We do only a basic initialization so that we can lock the pool.
+ This is required to cope with the case that this function is
+ called by some cleanup code at a point where the RNG has never
+ been initialized. */
+ initialize_basics ();
+ lock_pool ();
+
+ if ( !seed_file_name || !rndpool || !pool_filled )
+ {
+ unlock_pool ();
+ return;
+ }
+ if ( !allow_seed_file_update )
+ {
+ unlock_pool ();
+ log_info(_("note: random_seed file not updated\n"));
+ return;
+ }
+
+ /* At this point we know that there is something in the pool and
+ thus we can conclude that the pool has been fully initialized. */
+
+
+ /* Copy the entropy pool to a scratch pool and mix both of them. */
+ for (i=0,dp=(unsigned long*)(void*)keypool, sp=(unsigned long*)(void*)rndpool;
+ i < POOLWORDS; i++, dp++, sp++ )
+ {
+ *dp = *sp + ADD_VALUE;
+ }
+ mix_pool(rndpool); rndstats.mixrnd++;
+ mix_pool(keypool); rndstats.mixkey++;
+
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
+ fd = my_open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
+ S_IRUSR|S_IWUSR );
+#else
+# if LOCK_SEED_FILE
+ fd = my_open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
+# else
+ fd = my_open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
+# endif
+#endif
+
+ if (fd == -1 )
+ log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
+ else if (lock_seed_file (fd, seed_file_name, 1))
+ {
+ close (fd);
+ }
+#if LOCK_SEED_FILE
+ else if (ftruncate (fd, 0))
+ {
+ log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
+ close (fd);
+ }
+#endif /*LOCK_SEED_FILE*/
+ else
+ {
+ do
+ {
+ i = write (fd, keypool, POOLSIZE );
+ }
+ while (i == -1 && errno == EINTR);
+ if (i != POOLSIZE)
+ log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
+ if (close(fd))
+ log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
+ }
+
+ unlock_pool ();
+}
+
+
+/* Read random out of the pool. This function is the core of the
+ public random functions. Note that Level GCRY_WEAK_RANDOM is not
+ anymore handled special and in fact is an alias in the API for
+ level GCRY_STRONG_RANDOM. Must be called with the pool already
+ locked. */
+static void
+read_pool (byte *buffer, size_t length, int level)
+{
+ int i;
+ unsigned long *sp, *dp;
+ /* The volatile is there to make sure the compiler does not optimize
+ the code away in case the getpid function is badly attributed.
+ Note that we keep a pid in a static variable as well as in a
+ stack based one; the latter is to detect ill behaving thread
+ libraries, ignoring the pool mutexes. */
+ static volatile pid_t my_pid = (pid_t)(-1);
+ volatile pid_t my_pid2;
+
+ gcry_assert (pool_is_locked);
+
+ retry:
+ /* Get our own pid, so that we can detect a fork. */
+ my_pid2 = getpid ();
+ if (my_pid == (pid_t)(-1))
+ my_pid = my_pid2;
+ if ( my_pid != my_pid2 )
+ {
+ /* We detected a plain fork; i.e. we are now the child. Update
+ the static pid and add some randomness. */
+ pid_t x;
+
+ my_pid = my_pid2;
+ x = my_pid;
+ add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
+ just_mixed = 0; /* Make sure it will get mixed. */
+ }
+
+ gcry_assert (pool_is_locked);
+
+ /* Our code does not allow to extract more than POOLSIZE. Better
+ check it here. */
+ if (length > POOLSIZE)
+ {
+ log_bug("too many random bits requested\n");
+ }
+
+ if (!pool_filled)
+ {
+ if (read_seed_file() )
+ pool_filled = 1;
+ }
+
+ /* For level 2 quality (key generation) we always make sure that the
+ pool has been seeded enough initially. */
+ if (level == GCRY_VERY_STRONG_RANDOM && !did_initial_extra_seeding)
+ {
+ size_t needed;
+
+ pool_balance = 0;
+ needed = length - pool_balance;
+ if (needed < 16) /* At least 128 bits. */
+ needed = 16;
+ else if( needed > POOLSIZE )
+ BUG ();
+ read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
+ GCRY_VERY_STRONG_RANDOM);
+ pool_balance += needed;
+ did_initial_extra_seeding = 1;
+ }
+
+ /* For level 2 make sure that there is enough random in the pool. */
+ if (level == GCRY_VERY_STRONG_RANDOM && pool_balance < length)
+ {
+ size_t needed;
+
+ if (pool_balance < 0)
+ pool_balance = 0;
+ needed = length - pool_balance;
+ if (needed > POOLSIZE)
+ BUG ();
+ read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
+ GCRY_VERY_STRONG_RANDOM);
+ pool_balance += needed;
+ }
+
+ /* Make sure the pool is filled. */
+ while (!pool_filled)
+ random_poll();
+
+ /* Always do a fast random poll (we have to use the unlocked version). */
+ do_fast_random_poll();
+
+ /* Mix the pid in so that we for sure won't deliver the same random
+ after a fork. */
+ {
+ pid_t apid = my_pid;
+ add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT);
+ }
+
+ /* Mix the pool (if add_randomness() didn't it). */
+ if (!just_mixed)
+ {
+ mix_pool(rndpool);
+ rndstats.mixrnd++;
+ }
+
+ /* Create a new pool. */
+ for(i=0,dp=(unsigned long*)(void*)keypool, sp=(unsigned long*)(void*)rndpool;
+ i < POOLWORDS; i++, dp++, sp++ )
+ *dp = *sp + ADD_VALUE;
+
+ /* Mix both pools. */
+ mix_pool(rndpool); rndstats.mixrnd++;
+ mix_pool(keypool); rndstats.mixkey++;
+
+ /* Read the requested data. We use a read pointer to read from a
+ different position each time. */
+ while (length--)
+ {
+ *buffer++ = keypool[pool_readpos++];
+ if (pool_readpos >= POOLSIZE)
+ pool_readpos = 0;
+ pool_balance--;
+ }
+
+ if (pool_balance < 0)
+ pool_balance = 0;
+
+ /* Clear the keypool. */
+ memset (keypool, 0, POOLSIZE);
+
+ /* We need to detect whether a fork has happened. A fork might have
+ an identical pool and thus the child and the parent could emit
+ the very same random number. This test here is to detect forks
+ in a multi-threaded process. It does not work with all thread
+ implementations in particular not with pthreads. However it is
+ good enough for GNU Pth. */
+ if ( getpid () != my_pid2 )
+ {
+ pid_t x = getpid();
+ add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
+ just_mixed = 0; /* Make sure it will get mixed. */
+ my_pid = x; /* Also update the static pid. */
+ goto retry;
+ }
+}
+
+
+
+/* Add LENGTH bytes of randomness from buffer to the pool. ORIGIN is
+ used to specify the randomness origin. This is one of the
+ RANDOM_ORIGIN_* values. */
+static void
+add_randomness (const void *buffer, size_t length, enum random_origins origin)
+{
+ const unsigned char *p = buffer;
+ size_t count = 0;
+
+ gcry_assert (pool_is_locked);
+
+ rndstats.addbytes += length;
+ rndstats.naddbytes++;
+ while (length-- )
+ {
+ rndpool[pool_writepos++] ^= *p++;
+ count++;
+ if (pool_writepos >= POOLSIZE )
+ {
+ /* It is possible that we are invoked before the pool is
+ filled using an unreliable origin of entropy, for example
+ the fast random poll. To avoid flagging the pool as
+ filled in this case, we track the initial filling state
+ separately. See also the remarks about the seed file. */
+ if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled)
+ {
+ pool_filled_counter += count;
+ count = 0;
+ if (pool_filled_counter >= POOLSIZE)
+ pool_filled = 1;
+ }
+ pool_writepos = 0;
+ mix_pool(rndpool); rndstats.mixrnd++;
+ just_mixed = !length;
+ }
+ }
+}
+
+
+
+static void
+random_poll()
+{
+ rndstats.slowpolls++;
+ read_random_source (RANDOM_ORIGIN_SLOWPOLL, POOLSIZE/5, GCRY_STRONG_RANDOM);
+}
+
+
+/* Runtime determination of the slow entropy gathering module. */
+static int (*
+getfnc_gather_random (void))(void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins, size_t, int)
+{
+ int (*fnc)(void (*)(const void*, size_t, enum random_origins),
+ enum random_origins, size_t, int);
+
+#if USE_RNDLINUX
+ if ( !access (NAME_OF_DEV_RANDOM, R_OK)
+ && !access (NAME_OF_DEV_URANDOM, R_OK))
+ {
+ fnc = _gcry_rndlinux_gather_random;
+ return fnc;
+ }
+#endif
+
+#if USE_RNDEGD
+ if ( _gcry_rndegd_connect_socket (1) != -1 )
+ {
+ fnc = _gcry_rndegd_gather_random;
+ return fnc;
+ }
+#endif
+
+#if USE_RNDUNIX
+ fnc = _gcry_rndunix_gather_random;
+ return fnc;
+#endif
+
+#if USE_RNDW32
+ fnc = _gcry_rndw32_gather_random;
+ return fnc;
+#endif
+
+#if USE_RNDW32CE
+ fnc = _gcry_rndw32ce_gather_random;
+ return fnc;
+#endif
+
+ log_fatal (_("no entropy gathering module detected\n"));
+
+ return NULL; /*NOTREACHED*/
+}
+
+/* Runtime determination of the fast entropy gathering function.
+ (Currently a compile time method is used.) */
+static void (*
+getfnc_fast_random_poll (void))( void (*)(const void*, size_t,
+ enum random_origins),
+ enum random_origins)
+{
+#if USE_RNDW32
+ return _gcry_rndw32_gather_random_fast;
+#endif
+#if USE_RNDW32CE
+ return _gcry_rndw32ce_gather_random_fast;
+#endif
+ return NULL;
+}
+
+
+
+static void
+do_fast_random_poll (void)
+{
+ gcry_assert (pool_is_locked);
+
+ rndstats.fastpolls++;
+
+ if (fast_gather_fnc)
+ fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL);
+
+ /* Continue with the generic functions. */
+#if HAVE_GETHRTIME
+ {
+ hrtime_t tv;
+ tv = gethrtime();
+ add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL );
+ }
+#elif HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+ if( gettimeofday( &tv, NULL ) )
+ BUG();
+ add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
+ add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL );
+ }
+#elif HAVE_CLOCK_GETTIME
+ { struct timespec tv;
+ if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
+ BUG();
+ add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
+ add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), RANDOM_ORIGIN_FASTPOLL );
+ }
+#else /* use times */
+# ifndef HAVE_DOSISH_SYSTEM
+ { struct tms buf;
+ times( &buf );
+ add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
+ }
+# endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
+# ifdef RUSAGE_SELF
+ {
+ struct rusage buf;
+ /* QNX/Neutrino does return ENOSYS - so we just ignore it and add
+ whatever is in buf. In a chroot environment it might not work
+ at all (i.e. because /proc/ is not accessible), so we better
+ ignore all error codes and hope for the best. */
+ getrusage (RUSAGE_SELF, &buf );
+ add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
+ memset( &buf, 0, sizeof buf );
+ }
+# else /*!RUSAGE_SELF*/
+# ifdef __GCC__
+# warning There is no RUSAGE_SELF on this system
+# endif
+# endif /*!RUSAGE_SELF*/
+#endif /*HAVE_GETRUSAGE*/
+
+ /* Time and clock are available on all systems - so we better do it
+ just in case one of the above functions didn't work. */
+ {
+ time_t x = time(NULL);
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
+ }
+ {
+ clock_t x = clock();
+ add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
+ }
+
+ /* If the system features a fast hardware RNG, read some bytes from
+ there. */
+ _gcry_rndhw_poll_fast (add_randomness, RANDOM_ORIGIN_FASTPOLL);
+}
+
+
+/* The fast random pool function as called at some places in
+ libgcrypt. This is merely a wrapper to make sure that this module
+ is initialized and to lock the pool. Note, that this function is a
+ NOP unless a random function has been used or _gcry_initialize (1)
+ has been used. We use this hack so that the internal use of this
+ function in cipher_open and md_open won't start filling up the
+ random pool, even if no random will be required by the process. */
+void
+_gcry_rngcsprng_fast_poll (void)
+{
+ initialize_basics ();
+
+ lock_pool ();
+ if (rndpool)
+ {
+ /* Yes, we are fully initialized. */
+ do_fast_random_poll ();
+ }
+ unlock_pool ();
+}
+
+
+
+static void
+read_random_source (enum random_origins origin, size_t length, int level)
+{
+ if ( !slow_gather_fnc )
+ log_fatal ("Slow entropy gathering module not yet initialized\n");
+
+ if (slow_gather_fnc (add_randomness, origin, length, level) < 0)
+ log_fatal ("No way to gather entropy for the RNG\n");
+}
diff --git a/comm/third_party/libgcrypt/random/random-daemon.c b/comm/third_party/libgcrypt/random/random-daemon.c
new file mode 100644
index 0000000000..8ea4df285b
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/random-daemon.c
@@ -0,0 +1,336 @@
+/* random-daemon.c - Access to the external random daemon
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ The functions here are used by random.c to divert calls to an
+ external random number daemon. The actual daemon we use is
+ gcryptrnd. Such a daemon is useful to keep a persistent pool in
+ memory over invocations of a single application and to allow
+ prioritizing access to the actual entropy sources. The drawback is
+ that we need to use IPC (i.e. unix domain socket) to convey
+ sensitive data.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "g10lib.h"
+#include "random.h"
+
+
+
+/* This is default socket name we use in case the provided socket name
+ is NULL. */
+#define RANDOM_DAEMON_SOCKET "/var/run/libgcrypt/S.gcryptrnd"
+
+/* The lock serializing access to the daemon. */
+GPGRT_LOCK_DEFINE (daemon_lock);
+
+/* The socket connected to the daemon. */
+static int daemon_socket = -1;
+
+/* Creates a socket connected to the daemon. On success, store the
+ socket fd in *SOCK. Returns error code. */
+static gcry_error_t
+connect_to_socket (const char *socketname, int *sock)
+{
+ struct sockaddr_un *srvr_addr;
+ socklen_t addrlen;
+ gcry_error_t err;
+ int fd;
+ int rc;
+
+ srvr_addr = NULL;
+
+ /* Create a socket. */
+ fd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ log_error ("can't create socket: %s\n", strerror (errno));
+ err = gcry_error_from_errno (errno);
+ goto out;
+ }
+
+ /* Set up address. */
+ srvr_addr = gcry_malloc (sizeof *srvr_addr);
+ if (! srvr_addr)
+ {
+ log_error ("malloc failed: %s\n", strerror (errno));
+ err = gcry_error_from_errno (errno);
+ goto out;
+ }
+ memset (srvr_addr, 0, sizeof *srvr_addr);
+ srvr_addr->sun_family = AF_UNIX;
+ if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path))
+ {
+ log_error ("socket name `%s' too long\n", socketname);
+ err = gcry_error (GPG_ERR_ENAMETOOLONG);
+ goto out;
+ }
+ strcpy (srvr_addr->sun_path, socketname);
+ addrlen = (offsetof (struct sockaddr_un, sun_path)
+ + strlen (srvr_addr->sun_path) + 1);
+
+ /* Connect socket. */
+ rc = connect (fd, (struct sockaddr *) srvr_addr, addrlen);
+ if (rc == -1)
+ {
+ log_error ("error connecting socket `%s': %s\n",
+ srvr_addr->sun_path, strerror (errno));
+ err = gcry_error_from_errno (errno);
+ goto out;
+ }
+
+ err = 0;
+
+ out:
+
+ gcry_free (srvr_addr);
+ if (err)
+ {
+ close (fd);
+ fd = -1;
+ }
+ *sock = fd;
+
+ return err;
+}
+
+
+/* Initialize basics of this module. This should be viewed as a
+ constructor to prepare locking. */
+void
+_gcry_daemon_initialize_basics (void)
+{
+ /* Not anymore required. */
+}
+
+
+
+/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on
+ success or another value on write error. */
+static int
+writen (int fd, const void *buffer, size_t length)
+{
+ ssize_t n;
+
+ while (length)
+ {
+ do
+ n = ath_write (fd, buffer, length);
+ while (n < 0 && errno == EINTR);
+ if (n < 0)
+ {
+ log_error ("write error: %s\n", strerror (errno));
+ return -1; /* write error */
+ }
+ length -= n;
+ buffer = (const char*)buffer + n;
+ }
+ return 0; /* Okay */
+}
+
+static int
+readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
+{
+ size_t nleft = buflen;
+ int nread;
+ char *p;
+
+ p = buf;
+ while (nleft > 0)
+ {
+ nread = ath_read (fd, buf, nleft);
+ if (nread < 0)
+ {
+ if (nread == EINTR)
+ nread = 0;
+ else
+ return -1;
+ }
+ else if (!nread)
+ break; /* EOF */
+ nleft -= nread;
+ buf = (char*)buf + nread;
+ }
+ if (ret_nread)
+ *ret_nread = buflen - nleft;
+ return 0;
+}
+
+/* This functions requests REQ_NBYTES from the daemon. If NONCE is
+ true, the data should be suited for a nonce. If NONCE is FALSE,
+ data of random level LEVEL will be generated. The retrieved random
+ data will be stored in BUFFER. Returns error code. */
+static gcry_error_t
+call_daemon (const char *socketname,
+ void *buffer, size_t req_nbytes, int nonce,
+ enum gcry_random_level level)
+{
+ static int initialized;
+ unsigned char buf[255];
+ gcry_error_t err = 0;
+ size_t nbytes;
+ size_t nread;
+ int rc;
+
+ if (!req_nbytes)
+ return 0;
+
+ gpgrt_lock_lock (&daemon_lock);
+
+ /* Open the socket if that has not been done. */
+ if (!initialized)
+ {
+ initialized = 1;
+ err = connect_to_socket (socketname ? socketname : RANDOM_DAEMON_SOCKET,
+ &daemon_socket);
+ if (err)
+ {
+ daemon_socket = -1;
+ log_info ("not using random daemon\n");
+ gpgrt_lock_unlock (&daemon_lock);
+ return err;
+ }
+ }
+
+ /* Check that we have a valid socket descriptor. */
+ if ( daemon_socket == -1 )
+ {
+ gpgrt_lock_unlock (&daemon_lock);
+ return gcry_error (GPG_ERR_INTERNAL);
+ }
+
+
+ /* Do the real work. */
+
+ do
+ {
+ /* Process in chunks. */
+ nbytes = req_nbytes > sizeof (buf) ? sizeof (buf) : req_nbytes;
+ req_nbytes -= nbytes;
+
+ /* Construct request. */
+ buf[0] = 3;
+ if (nonce)
+ buf[1] = 10;
+ else if (level == GCRY_VERY_STRONG_RANDOM)
+ buf[1] = 12;
+ else if (level == GCRY_STRONG_RANDOM)
+ buf[1] = 11;
+ buf[2] = nbytes;
+
+ /* Send request. */
+ rc = writen (daemon_socket, buf, 3);
+ if (rc == -1)
+ {
+ err = gcry_error_from_errno (errno);
+ break;
+ }
+
+ /* Retrieve response. */
+
+ rc = readn (daemon_socket, buf, 2, &nread);
+ if (rc == -1)
+ {
+ err = gcry_error_from_errno (errno);
+ log_error ("read error: %s\n", _gcry_strerror (err));
+ break;
+ }
+ if (nread && buf[0])
+ {
+ log_error ("random daemon returned error code %d\n", buf[0]);
+ err = gcry_error (GPG_ERR_INTERNAL); /* ? */
+ break;
+ }
+ if (nread != 2)
+ {
+ log_error ("response too small\n");
+ err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
+ break;
+ }
+
+ /* if (1)*/ /* Do this in verbose mode? */
+ /* log_info ("received response with %d bytes of data\n", buf[1]);*/
+
+ if (buf[1] < nbytes)
+ {
+ log_error ("error: server returned less bytes than requested\n");
+ err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
+ break;
+ }
+ else if (buf[1] > nbytes)
+ {
+ log_error ("warning: server returned more bytes than requested\n");
+ err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
+ break;
+ }
+
+ assert (nbytes <= sizeof (buf));
+
+ rc = readn (daemon_socket, buf, nbytes, &nread);
+ if (rc == -1)
+ {
+ err = gcry_error_from_errno (errno);
+ log_error ("read error: %s\n", _gcry_strerror (err));
+ break;
+ }
+
+ if (nread != nbytes)
+ {
+ log_error ("too little random data read\n");
+ err = gcry_error (GPG_ERR_INTERNAL);
+ break;
+ }
+
+ /* Successfuly read another chunk of data. */
+ memcpy (buffer, buf, nbytes);
+ buffer = ((char *) buffer) + nbytes;
+ }
+ while (req_nbytes);
+
+ gpgrt_lock_unlock (&daemon_lock);
+
+ return err;
+}
+
+/* Internal function to fill BUFFER with LENGTH bytes of random. We
+ support GCRY_STRONG_RANDOM and GCRY_VERY_STRONG_RANDOM here.
+ Return 0 on success. */
+int
+_gcry_daemon_randomize (const char *socketname,
+ void *buffer, size_t length,
+ enum gcry_random_level level)
+{
+ gcry_error_t err;
+
+ err = call_daemon (socketname, buffer, length, 0, level);
+
+ return err ? -1 : 0;
+}
+
+/* END */
diff --git a/comm/third_party/libgcrypt/random/random-drbg.c b/comm/third_party/libgcrypt/random/random-drbg.c
new file mode 100644
index 0000000000..6124f5fb6d
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/random-drbg.c
@@ -0,0 +1,2668 @@
+/* random-drbg.c - Deterministic Random Bits Generator
+ * Copyright 2014 Stephan Mueller <smueller@chronox.de>
+ *
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * LGPLv2+, in which case the provisions of the LGPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the LGPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * gcry_control GCRYCTL_DRBG_REINIT
+ * ================================
+ * This control request re-initializes the DRBG completely, i.e. the entire
+ * state of the DRBG is zeroized (with two exceptions listed in
+ * GCRYCTL_DRBG_SET_ENTROPY).
+ *
+ * The control request takes the following values which influences how
+ * the DRBG is re-initialized:
+ *
+ * - const char *flagstr
+ *
+ * This variable specifies the DRBG type to be used for the next
+ * initialization. If set to NULL, the previous DRBG type is
+ * used for the initialization. If not NULL a space separated
+ * list of tokens with associated flag values is expected which
+ * are ORed to form the mandatory flags of the requested DRBG
+ * strength and cipher type. Optionally, the prediction
+ * resistance flag can be ORed into the flags variable.
+ *
+ * | String token | Flag value |
+ * |--------------+------------------------|
+ * | aes | DRBG_CTRAES |
+ * | serpent | DRBG_CTRSERPENT |
+ * | twofish | DRBG_CTRTWOFISH |
+ * | sha1 | DRBG_HASHSHA1 |
+ * | sha256 | DRBG_HASHSHA256 |
+ * | sha512 | DRBG_HASHSHA512 |
+ * | hmac | DRBG_HMAC |
+ * | sym128 | DRBG_SYM128 |
+ * | sym192 | DRBG_SYM192 |
+ * | sym256 | DRBG_SYM256 |
+ * | pr | DRBG_PREDICTION_RESIST |
+ *
+ * For example:
+ *
+ * - CTR-DRBG with AES-128 without prediction resistance:
+ * "aes sym128"
+ * - HMAC-DRBG with SHA-512 with prediction resistance:
+ * "hmac sha512 pr"
+ *
+ * - gcry_buffer_t *pers
+ *
+ * NULL terminated array with personalization strings to be used
+ * for initialization.
+ *
+ * - int npers
+ *
+ * Size of PERS.
+ *
+ * - void *guard
+ *
+ * A value of NULL must be passed for this.
+ *
+ * The variable of flags is independent from the pers/perslen variables. If
+ * flags is set to 0 and perslen is set to 0, the current DRBG type is
+ * completely reset without using a personalization string.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * drbg_string_t pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string without changing the DRBG type
+ * ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers);
+ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * drbg_string_t addtl;
+ * char addtl_string[11] = "some-string";
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * // The following call is a wrapper to gcry_randomize() and returns
+ * // the same error codes.
+ * gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ *
+ *
+ * Switch the DRBG type to some other type
+ * ---------------------------------------
+ * // Switch to CTR DRBG AES-128 without prediction resistance
+ * ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL);
+ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include "g10lib.h"
+#include "random.h"
+#include "rand-internal.h"
+#include "../cipher/bufhelp.h"
+
+
+
+/******************************************************************
+ * Constants
+ ******************************************************************/
+
+/*
+ * DRBG flags bitmasks
+ *
+ * 31 (B) 28 19 (A) 0
+ * +-+-+-+--------+---+-----------+-----+
+ * |~|~|u|~~~~~~~~| 3 | 2 | 1 |
+ * +-+-+-+--------+- -+-----------+-----+
+ * ctl flg| |drbg use selection flags
+ *
+ */
+
+/* Internal state control flags (B) */
+#define DRBG_PREDICTION_RESIST ((u32)1<<28)
+
+/* CTR type modifiers (A.1)*/
+#define DRBG_CTRAES ((u32)1<<0)
+#define DRBG_CTRSERPENT ((u32)1<<1)
+#define DRBG_CTRTWOFISH ((u32)1<<2)
+#define DRBG_CTR_MASK (DRBG_CTRAES | DRBG_CTRSERPENT \
+ | DRBG_CTRTWOFISH)
+
+/* HASH type modifiers (A.2)*/
+#define DRBG_HASHSHA1 ((u32)1<<4)
+#define DRBG_HASHSHA224 ((u32)1<<5)
+#define DRBG_HASHSHA256 ((u32)1<<6)
+#define DRBG_HASHSHA384 ((u32)1<<7)
+#define DRBG_HASHSHA512 ((u32)1<<8)
+#define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 \
+ | DRBG_HASHSHA256 | DRBG_HASHSHA384 \
+ | DRBG_HASHSHA512)
+/* type modifiers (A.3)*/
+#define DRBG_HMAC ((u32)1<<12)
+#define DRBG_SYM128 ((u32)1<<13)
+#define DRBG_SYM192 ((u32)1<<14)
+#define DRBG_SYM256 ((u32)1<<15)
+#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_SYM128 | DRBG_SYM192 \
+ | DRBG_SYM256)
+#define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK \
+ | DRBG_TYPE_MASK)
+
+#define DRBG_PR_CTRAES128 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM128)
+#define DRBG_PR_CTRAES192 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM192)
+#define DRBG_PR_CTRAES256 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM256)
+#define DRBG_NOPR_CTRAES128 (DRBG_CTRAES | DRBG_SYM128)
+#define DRBG_NOPR_CTRAES192 (DRBG_CTRAES | DRBG_SYM192)
+#define DRBG_NOPR_CTRAES256 (DRBG_CTRAES | DRBG_SYM256)
+#define DRBG_PR_HASHSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1)
+#define DRBG_PR_HASHSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256)
+#define DRBG_PR_HASHSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384)
+#define DRBG_PR_HASHSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512)
+#define DRBG_NOPR_HASHSHA1 (DRBG_HASHSHA1)
+#define DRBG_NOPR_HASHSHA256 (DRBG_HASHSHA256)
+#define DRBG_NOPR_HASHSHA384 (DRBG_HASHSHA384)
+#define DRBG_NOPR_HASHSHA512 (DRBG_HASHSHA512)
+#define DRBG_PR_HMACSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1 \
+ | DRBG_HMAC)
+#define DRBG_PR_HMACSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256 \
+ | DRBG_HMAC)
+#define DRBG_PR_HMACSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384 \
+ | DRBG_HMAC)
+#define DRBG_PR_HMACSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512 \
+ | DRBG_HMAC)
+#define DRBG_NOPR_HMACSHA1 (DRBG_HASHSHA1 | DRBG_HMAC)
+#define DRBG_NOPR_HMACSHA256 (DRBG_HASHSHA256 | DRBG_HMAC)
+#define DRBG_NOPR_HMACSHA384 (DRBG_HASHSHA384 | DRBG_HMAC)
+#define DRBG_NOPR_HMACSHA512 (DRBG_HASHSHA512 | DRBG_HMAC)
+
+
+/* The default DRGB type. */
+#define DRBG_DEFAULT_TYPE DRBG_NOPR_HMACSHA256
+
+
+#define DRBG_CTR_NULL_LEN 128
+
+
+/******************************************************************
+ * Common data structures
+ ******************************************************************/
+
+/*
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+struct drbg_string_s
+{
+ const unsigned char *buf;
+ size_t len;
+ struct drbg_string_s *next;
+};
+typedef struct drbg_string_s drbg_string_t;
+
+
+/* DRBG input data structure for DRBG generate with additional
+ * information string. */
+struct drbg_gen_s
+{
+ unsigned char *outbuf; /* output buffer for random numbers */
+ unsigned int outlen; /* size of output buffer */
+ drbg_string_t *addtl; /* input buffer for
+ * additional information string */
+};
+typedef struct drbg_gen_s drbg_gen_t;
+
+
+/* Forward declaration of the state object pointer. */
+struct drbg_state_s;
+typedef struct drbg_state_s *drbg_state_t;
+
+
+struct drbg_core_s
+{
+ u32 flags; /* flags for the cipher */
+ ushort statelen; /* maximum state length */
+ ushort blocklen_bytes; /* block size of output in bytes */
+ int backend_cipher; /* libgcrypt backend cipher */
+};
+
+struct drbg_state_ops_s
+{
+ gpg_err_code_t (*update) (drbg_state_t drbg,
+ drbg_string_t *seed, int reseed);
+ gpg_err_code_t (*generate) (drbg_state_t drbg,
+ unsigned char *buf, unsigned int buflen,
+ drbg_string_t *addtl);
+ gpg_err_code_t (*crypto_init) (drbg_state_t drbg);
+ void (*crypto_fini) (drbg_state_t drbg);
+};
+
+struct drbg_test_data_s
+{
+ drbg_string_t *testentropy; /* TEST PARAMETER: test entropy */
+ int fail_seed_source:1; /* If set, the seed function will
+ * return an error. */
+};
+
+
+/* This state object keeps the state of an DRBG instance. */
+struct drbg_state_s
+{
+ unsigned char *V; /* internal state 10.1.1.1 1a) */
+ unsigned char *C; /* hash: static value 10.1.1.1 1b)
+ * hmac / ctr: key */
+ size_t reseed_ctr; /* Number of RNG requests since last reseed --
+ * 10.1.1.1 1c) */
+ unsigned char *scratchpad; /* some memory the DRBG can use for its
+ * operation -- allocated during init */
+ void *priv_data; /* Cipher handle */
+ gcry_cipher_hd_t ctr_handle; /* CTR mode cipher handle */
+ int seeded:1; /* DRBG fully seeded? */
+ int pr:1; /* Prediction resistance enabled? */
+ /* Taken from libgcrypt ANSI X9.31 DRNG: We need to keep track of the
+ * process which did the initialization so that we can detect a fork.
+ * The volatile modifier is required so that the compiler does not
+ * optimize it away in case the getpid function is badly attributed. */
+ pid_t seed_init_pid;
+ const struct drbg_state_ops_s *d_ops;
+ const struct drbg_core_s *core;
+ struct drbg_test_data_s *test_data;
+};
+
+enum drbg_prefixes
+{
+ DRBG_PREFIX0 = 0x00,
+ DRBG_PREFIX1,
+ DRBG_PREFIX2,
+ DRBG_PREFIX3
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+/***************************************************************
+ * Global variables
+ ***************************************************************/
+
+/* Global state variable holding the current instance of the DRBG. */
+static drbg_state_t drbg_state;
+
+/* This is the lock variable we use to serialize access to this RNG. */
+GPGRT_LOCK_DEFINE(drbg_lock_var);
+
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+static const struct drbg_core_s drbg_cores[] = {
+ /* Hash DRBGs */
+ {DRBG_HASHSHA1, 55, 20, GCRY_MD_SHA1},
+ {DRBG_HASHSHA256, 55, 32, GCRY_MD_SHA256},
+ {DRBG_HASHSHA384, 111, 48, GCRY_MD_SHA384},
+ {DRBG_HASHSHA512, 111, 64, GCRY_MD_SHA512},
+ /* HMAC DRBGs */
+ {DRBG_HASHSHA1 | DRBG_HMAC, 20, 20, GCRY_MD_SHA1},
+ {DRBG_HASHSHA256 | DRBG_HMAC, 32, 32, GCRY_MD_SHA256},
+ {DRBG_HASHSHA384 | DRBG_HMAC, 48, 48, GCRY_MD_SHA384},
+ {DRBG_HASHSHA512 | DRBG_HMAC, 64, 64, GCRY_MD_SHA512},
+ /* block ciphers */
+ {DRBG_CTRAES | DRBG_SYM128, 32, 16, GCRY_CIPHER_AES128},
+ {DRBG_CTRAES | DRBG_SYM192, 40, 16, GCRY_CIPHER_AES192},
+ {DRBG_CTRAES | DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256}
+};
+
+static gpg_err_code_t drbg_hash_init (drbg_state_t drbg);
+static gpg_err_code_t drbg_hmac_init (drbg_state_t drbg);
+static gpg_err_code_t drbg_hmac_setkey (drbg_state_t drbg,
+ const unsigned char *key);
+static void drbg_hash_fini (drbg_state_t drbg);
+static byte *drbg_hash (drbg_state_t drbg, const drbg_string_t *buf);
+static gpg_err_code_t drbg_sym_init (drbg_state_t drbg);
+static void drbg_sym_fini (drbg_state_t drbg);
+static gpg_err_code_t drbg_sym_setkey (drbg_state_t drbg,
+ const unsigned char *key);
+static gpg_err_code_t drbg_sym (drbg_state_t drbg, unsigned char *outval,
+ const drbg_string_t *buf);
+static gpg_err_code_t drbg_sym_ctr (drbg_state_t drbg,
+ const unsigned char *inbuf, unsigned int inbuflen,
+ unsigned char *outbuf, unsigned int outbuflen);
+
+/******************************************************************
+ ******************************************************************
+ ******************************************************************
+ * Generic DRBG code
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+#if 0
+#define dbg(x) do { log_debug x; } while(0)
+#else
+#define dbg(x)
+#endif
+
+/*
+ * Parse a string of flags and store the flag values at R_FLAGS.
+ * Return 0 on success.
+ */
+static gpg_err_code_t
+parse_flag_string (const char *string, u32 *r_flags)
+{
+ struct {
+ const char *name;
+ u32 flag;
+ } table[] = {
+ { "aes", DRBG_CTRAES },
+ { "serpent", DRBG_CTRSERPENT },
+ { "twofish", DRBG_CTRTWOFISH },
+ { "sha1", DRBG_HASHSHA1 },
+ { "sha256", DRBG_HASHSHA256 },
+ { "sha512", DRBG_HASHSHA512 },
+ { "hmac", DRBG_HMAC },
+ { "sym128", DRBG_SYM128 },
+ { "sym192", DRBG_SYM192 },
+ { "sym256", DRBG_SYM256 },
+ { "pr", DRBG_PREDICTION_RESIST }
+ };
+
+ *r_flags = 0;
+ if (string)
+ {
+ char **tl;
+ const char *s;
+ int i, j;
+
+ tl = _gcry_strtokenize (string, NULL);
+ if (!tl)
+ return gpg_err_code_from_syserror ();
+ for (i=0; (s=tl[i]); i++)
+ {
+ for (j=0; j < DIM (table); j++)
+ if (!strcmp (s, table[j].name))
+ {
+ *r_flags |= table[j].flag;
+ break;
+ }
+ if (!(j < DIM (table)))
+ {
+ xfree (tl);
+ return GPG_ERR_INV_FLAG;
+ }
+ }
+ xfree (tl);
+ }
+
+ return 0;
+}
+
+static inline void
+drbg_string_fill (drbg_string_t *string,
+ const unsigned char *buf, size_t len)
+{
+ string->buf = buf;
+ string->len = len;
+ string->next = NULL;
+}
+
+static inline ushort
+drbg_statelen (drbg_state_t drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->statelen;
+ return 0;
+}
+
+static inline ushort
+drbg_blocklen (drbg_state_t drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->blocklen_bytes;
+ return 0;
+}
+
+static inline ushort
+drbg_keylen (drbg_state_t drbg)
+{
+ if (drbg && drbg->core)
+ return (drbg->core->statelen - drbg->core->blocklen_bytes);
+ return 0;
+}
+
+static inline size_t
+drbg_max_request_bytes (void)
+{
+ /* SP800-90A requires the limit 2**19 bits, but we return bytes */
+ return (1 << 16);
+}
+
+static inline size_t
+drbg_max_addtl (void)
+{
+ /* SP800-90A requires 2**35 bytes additional info str / pers str */
+#ifdef __LP64__
+ return (1UL << 35);
+#else
+ /*
+ * SP800-90A allows smaller maximum numbers to be returned -- we
+ * return SIZE_MAX - 1 to allow the verification of the enforcement
+ * of this value in drbg_healthcheck_sanity.
+ */
+ return (SIZE_MAX - 1);
+#endif
+}
+
+static inline size_t
+drbg_max_requests (void)
+{
+ /* SP800-90A requires 2**48 maximum requests before reseeding */
+#ifdef __LP64__
+ return (1UL << 48);
+#else
+ return SIZE_MAX;
+#endif
+}
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * flags: DRBG flags reference
+ *
+ * Return: normalized strength value or 32 as a default to counter
+ * programming errors
+ */
+static inline unsigned short
+drbg_sec_strength (u32 flags)
+{
+ if ((flags & DRBG_HASHSHA1) || (flags & DRBG_SYM128))
+ return 16;
+ else if (flags & DRBG_SYM192)
+ return 24;
+ else if ((flags & DRBG_SYM256) || (flags & DRBG_HASHSHA256) ||
+ (flags & DRBG_HASHSHA384) || (flags & DRBG_HASHSHA512))
+ return 32;
+ else
+ return 32;
+}
+
+static void
+drbg_add_buf (unsigned char *dst, size_t dstlen,
+ unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr, *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen - 1);
+ addptr = add + (addlen - 1);
+ while (len)
+ {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--;
+ dstptr--;
+ addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0)
+ {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--;
+ dstptr--;
+ }
+}
+
+/* Helper variables for read_cb().
+ *
+ * The _gcry_rnd*_gather_random interface does not allow to provide a
+ * data pointer. Thus we need to use a global variable for
+ * communication. However, the then required locking is anyway a good
+ * idea because it does not make sense to have several readers of (say
+ * /dev/random). It is easier to serve them one after the other.
+ */
+static unsigned char *read_cb_buffer; /* The buffer. */
+static size_t read_cb_size; /* Size of the buffer. */
+static size_t read_cb_len; /* Used length. */
+
+/* Callback for generating seed from kernel device. */
+static void
+drbg_read_cb (const void *buffer, size_t length,
+ enum random_origins origin)
+{
+ const unsigned char *p = buffer;
+
+ (void) origin;
+ gcry_assert (read_cb_buffer);
+
+ /* Note that we need to protect against gatherers returning more
+ * than the requested bytes (e.g. rndw32). */
+ while (length-- && read_cb_len < read_cb_size)
+ read_cb_buffer[read_cb_len++] = *p++;
+}
+
+static inline int
+drbg_get_entropy (drbg_state_t drbg, unsigned char *buffer,
+ size_t len)
+{
+ int rc = 0;
+
+ /* Perform testing as defined in 11.3.2 */
+ if (drbg->test_data && drbg->test_data->fail_seed_source)
+ return -1;
+
+ read_cb_buffer = buffer;
+ read_cb_size = len;
+ read_cb_len = 0;
+#if USE_RNDLINUX
+ rc = _gcry_rndlinux_gather_random (drbg_read_cb, 0, len,
+ GCRY_VERY_STRONG_RANDOM);
+#elif USE_RNDUNIX
+ rc = _gcry_rndunix_gather_random (drbg_read_cb, 0, len,
+ GCRY_VERY_STRONG_RANDOM);
+#elif USE_RNDW32
+ do
+ {
+ rc = _gcry_rndw32_gather_random (drbg_read_cb, 0, len,
+ GCRY_VERY_STRONG_RANDOM);
+ }
+ while (rc >= 0 && read_cb_len < read_cb_size);
+#else
+ rc = -1;
+#endif
+ return rc;
+}
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static gpg_err_code_t
+drbg_ctr_bcc (drbg_state_t drbg,
+ unsigned char *out, const unsigned char *key,
+ drbg_string_t *in)
+{
+ gpg_err_code_t ret = GPG_ERR_GENERAL;
+ drbg_string_t *curr = in;
+ size_t inpos = curr->len;
+ const unsigned char *pos = curr->buf;
+ drbg_string_t data;
+
+ drbg_string_fill (&data, out, drbg_blocklen (drbg));
+
+ /* 10.4.3 step 1 */
+ memset (out, 0, drbg_blocklen (drbg));
+
+ ret = drbg_sym_setkey(drbg, key);
+ if (ret)
+ return ret;
+
+ /* 10.4.3 step 2 / 4 */
+ while (inpos)
+ {
+ short cnt = 0;
+ /* 10.4.3 step 4.1 */
+ for (cnt = 0; cnt < drbg_blocklen (drbg); cnt++)
+ {
+ out[cnt] ^= *pos;
+ pos++;
+ inpos--;
+ /* the following branch implements the linked list
+ * iteration. If we are at the end of the current data
+ * set, we have to start using the next data set if
+ * available -- the inpos value always points to the
+ * current byte and will be zero if we have processed
+ * the last byte of the last linked list member */
+ if (0 == inpos)
+ {
+ curr = curr->next;
+ if (NULL != curr)
+ {
+ pos = curr->buf;
+ inpos = curr->len;
+ }
+ else
+ {
+ inpos = 0;
+ break;
+ }
+ }
+ }
+ /* 10.4.3 step 4.2 */
+ ret = drbg_sym (drbg, out, &data);
+ if (ret)
+ return ret;
+ /* 10.4.3 step 2 */
+ }
+ return 0;
+}
+
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
+ * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
+ * the scratchpad is used as follows:
+ * drbg_ctr_update:
+ * temp
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg) + drbg_blocklen(drbg)
+ * note: the cipher writing into this variable works
+ * blocklen-wise. Now, when the statelen is not a multiple
+ * of blocklen, the generateion loop below "spills over"
+ * by at most blocklen. Thus, we need to give sufficient
+ * memory.
+ * df_data
+ * start: drbg->scratchpad +
+ * drbg_statelen(drbg) +
+ * drbg_blocklen(drbg)
+ * length: drbg_statelen(drbg)
+ *
+ * drbg_ctr_df:
+ * pad
+ * start: df_data + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ * iv
+ * start: pad + drbg_blocklen(drbg)
+ * length: drbg_blocklen(drbg)
+ * temp
+ * start: iv + drbg_blocklen(drbg)
+ * length: drbg_satelen(drbg) + drbg_blocklen(drbg)
+ * note: temp is the buffer that the BCC function operates
+ * on. BCC operates blockwise. drbg_statelen(drbg)
+ * is sufficient when the DRBG state length is a multiple
+ * of the block size. For AES192 (and maybe other ciphers)
+ * this is not correct and the length for temp is
+ * insufficient (yes, that also means for such ciphers,
+ * the final output of all BCC rounds are truncated).
+ * Therefore, add drbg_blocklen(drbg) to cover all
+ * possibilities.
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static gpg_err_code_t
+drbg_ctr_df (drbg_state_t drbg, unsigned char *df_data,
+ size_t bytes_to_return, drbg_string_t *addtl)
+{
+ gpg_err_code_t ret = GPG_ERR_GENERAL;
+ unsigned char L_N[8];
+ /* S3 is input */
+ drbg_string_t S1, S2, S4, cipherin;
+ drbg_string_t *tempstr = addtl;
+ unsigned char *pad = df_data + drbg_statelen (drbg);
+ unsigned char *iv = pad + drbg_blocklen (drbg);
+ unsigned char *temp = iv + drbg_blocklen (drbg);
+ size_t padlen = 0;
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ const unsigned char *K = (unsigned char *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
+ unsigned char *X;
+ size_t generated_len = 0;
+ size_t inputlen = 0;
+
+ memset (pad, 0, drbg_blocklen (drbg));
+ memset (iv, 0, drbg_blocklen (drbg));
+ memset (temp, 0, drbg_statelen (drbg));
+
+ /* 10.4.2 step 1 is implicit as we work byte-wise */
+
+ /* 10.4.2 step 2 */
+ if ((512 / 8) < bytes_to_return)
+ return GPG_ERR_INV_ARG;
+
+ /* 10.4.2 step 2 -- calculate the entire length of all input data */
+ for (; NULL != tempstr; tempstr = tempstr->next)
+ inputlen += tempstr->len;
+ buf_put_be32 (&L_N[0], inputlen);
+
+ /* 10.4.2 step 3 */
+ buf_put_be32 (&L_N[4], bytes_to_return);
+
+ /* 10.4.2 step 5: length is size of L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof (L_N) + 1) % (drbg_blocklen (drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen (drbg) - padlen;
+ /* pad / padlen contains the 0x80 byte and the following zero bytes, so
+ * add one for byte for 0x80 */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill (&S1, iv, drbg_blocklen (drbg));
+ drbg_string_fill (&S2, L_N, sizeof (L_N));
+ drbg_string_fill (&S4, pad, padlen);
+ S1.next = &S2;
+ S2.next = addtl;
+
+ /* Splice in addtl between S2 and S4 -- we place S4 at the end of the
+ * input data chain. As this code is only triggered when addtl is not
+ * NULL, no NULL checks are necessary.*/
+ tempstr = addtl;
+ while (tempstr->next)
+ tempstr = tempstr->next;
+ tempstr->next = &S4;
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen (drbg) + (drbg_blocklen (drbg))))
+ {
+ /* 10.4.2 step 9.1 - the padding is implicit as the buffer
+ * holds zeros after allocation -- even the increment of i
+ * is irrelevant as the increment remains within length of i */
+ buf_put_be32 (iv, i);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc (drbg, temp + templen, K, &S1);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen (drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ /* implicit key len with seedlen - blocklen according to table 3 */
+ X = temp + (drbg_keylen (drbg));
+ drbg_string_fill (&cipherin, X, drbg_blocklen (drbg));
+
+ /* 10.4.2 step 12: overwriting of outval */
+
+ /* 10.4.2 step 13 */
+ ret = drbg_sym_setkey(drbg, temp);
+ if (ret)
+ goto out;
+ while (generated_len < bytes_to_return)
+ {
+ short blocklen = 0;
+ /* 10.4.2 step 13.1 */
+ /* the truncation of the key length is implicit as the key
+ * is only drbg_blocklen in size -- check for the implementation
+ * of the cipher function callback */
+ ret = drbg_sym (drbg, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen (drbg) < (bytes_to_return - generated_len)) ?
+ drbg_blocklen (drbg) : (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy (df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+ out:
+ memset (iv, 0, drbg_blocklen (drbg));
+ memset (temp, 0, drbg_statelen (drbg));
+ memset (pad, 0, drbg_blocklen (drbg));
+ return ret;
+}
+
+/*
+ * Update function of CTR DRBG as defined in 10.2.1.2
+ *
+ * The reseed variable has an enhanced meaning compared to the update
+ * functions of the other DRBGs as follows:
+ * 0 => initial seed from initialization
+ * 1 => reseed via drbg_seed
+ * 2 => first invocation from drbg_ctr_update when addtl is present. In
+ * this case, the df_data scratchpad is not deleted so that it is
+ * available for another calls to prevent calling the DF function
+ * again.
+ * 3 => second invocation from drbg_ctr_update. When the update function
+ * was called with addtl, the df_data memory already contains the
+ * DFed addtl information and we do not need to call DF again.
+ */
+static gpg_err_code_t
+drbg_ctr_update (drbg_state_t drbg, drbg_string_t *addtl, int reseed)
+{
+ gpg_err_code_t ret = GPG_ERR_GENERAL;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad +
+ drbg_statelen (drbg) + drbg_blocklen (drbg);
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg));
+ if (3 > reseed)
+ memset (df_data, 0, drbg_statelen (drbg));
+
+ if (!reseed)
+ {
+ /*
+ * The DRBG uses the CTR mode of the underlying AES cipher. The
+ * CTR mode increments the counter value after the AES operation
+ * but SP800-90A requires that the counter is incremented before
+ * the AES operation. Hence, we increment it at the time we set
+ * it by one.
+ */
+ drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
+
+ ret = _gcry_cipher_setkey (drbg->ctr_handle, drbg->C, drbg_keylen (drbg));
+ if (ret)
+ goto out;
+ }
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (addtl && 0 < addtl->len)
+ {
+ ret =
+ drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl);
+ if (ret)
+ goto out;
+ }
+
+ ret = drbg_sym_ctr (drbg, df_data, drbg_statelen(drbg),
+ temp, drbg_statelen(drbg));
+ if (ret)
+ goto out;
+
+ /* 10.2.1.2 step 5 */
+ ret = _gcry_cipher_setkey (drbg->ctr_handle, temp, drbg_keylen (drbg));
+ if (ret)
+ goto out;
+
+ /* 10.2.1.2 step 6 */
+ memcpy (drbg->V, temp + drbg_keylen (drbg), drbg_blocklen (drbg));
+ /* See above: increment counter by one to compensate timing of CTR op */
+ drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
+ ret = 0;
+
+ out:
+ memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg));
+ if (2 != reseed)
+ memset (df_data, 0, drbg_statelen (drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static gpg_err_code_t
+drbg_ctr_generate (drbg_state_t drbg,
+ unsigned char *buf, unsigned int buflen,
+ drbg_string_t *addtl)
+{
+ static const unsigned char drbg_ctr_null[DRBG_CTR_NULL_LEN] = { 0, };
+ gpg_err_code_t ret = 0;
+
+ memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && 0 < addtl->len)
+ {
+ addtl->next = NULL;
+ ret = drbg_ctr_update (drbg, addtl, 2);
+ if (ret)
+ return ret;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ ret = drbg_sym_ctr (drbg, drbg_ctr_null, sizeof(drbg_ctr_null), buf, buflen);
+ if (ret)
+ goto out;
+
+ /* 10.2.1.5.2 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_ctr_update (drbg, addtl, 3);
+
+ out:
+ return ret;
+}
+
+static struct drbg_state_ops_s drbg_ctr_ops = {
+ drbg_ctr_update,
+ drbg_ctr_generate,
+ drbg_sym_init,
+ drbg_sym_fini,
+};
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+static gpg_err_code_t
+drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
+{
+ gpg_err_code_t ret = GPG_ERR_GENERAL;
+ int i = 0;
+ drbg_string_t seed1, seed2, cipherin;
+
+ if (!reseed)
+ {
+ /* 10.1.2.3 step 2 already implicitly covered with
+ * the initial memset(0) of drbg->C */
+ memset (drbg->V, 1, drbg_statelen (drbg));
+ ret = drbg_hmac_setkey (drbg, drbg->C);
+ if (ret)
+ return ret;
+ }
+
+ /* build linked list which implements the concatenation and fill
+ * first part*/
+ drbg_string_fill (&seed1, drbg->V, drbg_statelen (drbg));
+ /* buffer will be filled in for loop below with one byte */
+ drbg_string_fill (&seed2, NULL, 1);
+ seed1.next = &seed2;
+ /* seed may be NULL */
+ seed2.next = seed;
+
+ drbg_string_fill (&cipherin, drbg->V, drbg_statelen (drbg));
+ /* we execute two rounds of V/K massaging */
+ for (i = 2; 0 < i; i--)
+ {
+ byte *retval;
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ retval = drbg_hash (drbg, &seed1);
+ ret = drbg_hmac_setkey (drbg, retval);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ retval = drbg_hash (drbg, &cipherin);
+ memcpy(drbg->V, retval, drbg_blocklen (drbg));
+
+ /* 10.1.2.2 step 3 */
+ if (!seed || 0 == seed->len)
+ return ret;
+ }
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static gpg_err_code_t
+drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
+ drbg_string_t *addtl)
+{
+ gpg_err_code_t ret = 0;
+ unsigned int len = 0;
+ drbg_string_t data;
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && 0 < addtl->len)
+ {
+ addtl->next = NULL;
+ ret = drbg_hmac_update (drbg, addtl, 1);
+ if (ret)
+ return ret;
+ }
+
+ drbg_string_fill (&data, drbg->V, drbg_statelen (drbg));
+ while (len < buflen)
+ {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ byte *retval = drbg_hash (drbg, &data);
+ memcpy(drbg->V, retval, drbg_blocklen (drbg));
+ outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
+ drbg_blocklen (drbg) : (buflen - len);
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy (buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl)
+ addtl->next = NULL;
+ ret = drbg_hmac_update (drbg, addtl, 1);
+
+ return ret;
+}
+
+static struct drbg_state_ops_s drbg_hmac_ops = {
+ drbg_hmac_update,
+ drbg_hmac_generate,
+ drbg_hmac_init,
+ drbg_hash_fini,
+};
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ */
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static gpg_err_code_t
+drbg_hash_df (drbg_state_t drbg,
+ unsigned char *outval, size_t outlen,
+ drbg_string_t *entropy)
+{
+ size_t len = 0;
+ unsigned char input[5];
+ drbg_string_t data1;
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ buf_put_be32 (&input[1], (outlen * 8));
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill (&data1, input, 5);
+ data1.next = entropy;
+
+ /* 10.4.1 step 4 */
+ while (len < outlen)
+ {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ byte *retval = drbg_hash (drbg, &data1);
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen (drbg) < (outlen - len)) ?
+ drbg_blocklen (drbg) : (outlen - len);
+ memcpy (outval + len, retval, blocklen);
+ len += blocklen;
+ }
+
+ return 0;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static gpg_err_code_t
+drbg_hash_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
+{
+ gpg_err_code_t ret = 0;
+ drbg_string_t data1, data2;
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset (drbg->scratchpad, 0, drbg_statelen (drbg));
+ if (!seed)
+ return GPG_ERR_INV_ARG;
+
+ if (reseed)
+ {
+ /* 10.1.1.3 step 1: string length is concatenation of
+ * 1 byte, V and seed (which is concatenated entropy/addtl
+ * input)
+ */
+ memcpy (V, drbg->V, drbg_statelen (drbg));
+ drbg_string_fill (&data1, &prefix, 1);
+ drbg_string_fill (&data2, V, drbg_statelen (drbg));
+ data1.next = &data2;
+ data2.next = seed;
+ }
+ else
+ {
+ drbg_string_fill (&data1, seed->buf, seed->len);
+ data1.next = seed->next;
+ }
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df (drbg, drbg->V, drbg_statelen (drbg), &data1);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill (&data1, &prefix, 1);
+ drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
+ data1.next = &data2;
+ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
+ ret = drbg_hash_df (drbg, drbg->C, drbg_statelen (drbg), &data1);
+
+ out:
+ memset (drbg->scratchpad, 0, drbg_statelen (drbg));
+ return ret;
+}
+
+/* Processing of additional information string for Hash DRBG. */
+static gpg_err_code_t
+drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl)
+{
+ drbg_string_t data1, data2;
+ drbg_string_t *data3;
+ unsigned char prefix = DRBG_PREFIX2;
+ byte *retval;
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || 0 == addtl->len)
+ return 0;
+
+ /* 10.1.1.4 step 2a -- concatenation */
+ drbg_string_fill (&data1, &prefix, 1);
+ drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
+ data3 = addtl;
+ data1.next = &data2;
+ data2.next = data3;
+ data3->next = NULL;
+ /* 10.1.1.4 step 2a -- cipher invocation */
+ retval = drbg_hash (drbg, &data1);
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg));
+
+ return 0;
+}
+
+/*
+ * Hashgen defined in 10.1.1.4
+ */
+static gpg_err_code_t
+drbg_hash_hashgen (drbg_state_t drbg, unsigned char *buf, unsigned int buflen)
+{
+ unsigned int len = 0;
+ unsigned char *src = drbg->scratchpad;
+ drbg_string_t data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy (src, drbg->V, drbg_statelen (drbg));
+
+ drbg_string_fill (&data, src, drbg_statelen (drbg));
+ while (len < buflen)
+ {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ byte *retval = drbg_hash (drbg, &data);
+ outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
+ drbg_blocklen (drbg) : (buflen - len);
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy (buf + len, retval, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1);
+ }
+
+ memset (drbg->scratchpad, 0, drbg_statelen (drbg));
+ return 0;
+}
+
+/* Generate function for Hash DRBG as defined in 10.1.1.4 */
+static gpg_err_code_t
+drbg_hash_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
+ drbg_string_t *addtl)
+{
+ gpg_err_code_t ret;
+ unsigned char prefix = DRBG_PREFIX3;
+ drbg_string_t data1, data2;
+ byte *retval;
+ union
+ {
+ unsigned char req[8];
+ u64 req_int;
+ } u;
+
+ /* 10.1.1.4 step 2 */
+ ret = drbg_hash_process_addtl (drbg, addtl);
+ if (ret)
+ return ret;
+ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
+ * 10.1.1.4 */
+ ret = drbg_hash_hashgen (drbg, buf, buflen);
+ if (ret)
+ return ret;
+
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill (&data1, &prefix, 1);
+ drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
+ data1.next = &data2;
+
+ /* this is the value H as documented in 10.1.1.4 */
+ retval = drbg_hash (drbg, &data1);
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg));
+ drbg_add_buf (drbg->V, drbg_statelen (drbg), drbg->C, drbg_statelen (drbg));
+ u.req_int = be_bswap64 (drbg->reseed_ctr);
+ drbg_add_buf (drbg->V, drbg_statelen (drbg), u.req, sizeof (u.req));
+
+ return ret;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops_s drbg_hash_ops = {
+ drbg_hash_update,
+ drbg_hash_generate,
+ drbg_hash_init,
+ drbg_hash_fini,
+};
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static gpg_err_code_t
+drbg_seed (drbg_state_t drbg, drbg_string_t *pers, int reseed)
+{
+ gpg_err_code_t ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ drbg_string_t data1;
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl ()))
+ {
+ dbg (("DRBG: personalization string too long %lu\n", pers->len));
+ return GPG_ERR_INV_ARG;
+ }
+ if (drbg->test_data && drbg->test_data->testentropy)
+ {
+ drbg_string_fill (&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ dbg (("DRBG: using test entropy\n"));
+ }
+ else
+ {
+ /* Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding. */
+ entropylen = drbg_sec_strength (drbg->core->flags);
+ if (!entropylen)
+ return GPG_ERR_GENERAL;
+ if (0 == reseed)
+ /* make sure we round up strength/2 in
+ * case it is not divisible by 2 */
+ entropylen = ((entropylen + 1) / 2) * 3;
+ dbg (("DRBG: (re)seeding with %lu bytes of entropy\n", entropylen));
+ entropy = xcalloc_secure (1, entropylen);
+ if (!entropy)
+ return GPG_ERR_ENOMEM;
+ ret = drbg_get_entropy (drbg, entropy, entropylen);
+ if (ret)
+ goto out;
+ drbg_string_fill (&data1, entropy, entropylen);
+ }
+
+ /* concatenation of entropy with personalization str / addtl input)
+ * the variable pers is directly handed by the caller, check its
+ * contents whether it is appropriate */
+ if (pers && pers->buf && 0 < pers->len && NULL == pers->next)
+ {
+ data1.next = pers;
+ dbg (("DRBG: using personalization string\n"));
+ }
+
+ ret = drbg->d_ops->update (drbg, &data1, reseed);
+ dbg (("DRBG: state updated with seed\n"));
+ if (ret)
+ goto out;
+ drbg->seeded = 1;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+ out:
+ xfree (entropy);
+ return ret;
+}
+
+
+/*************************************************************************
+ * Exported interfaces.
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: Generated number of bytes.
+ */
+static gpg_err_code_t
+drbg_generate (drbg_state_t drbg,
+ unsigned char *buf, unsigned int buflen,
+ drbg_string_t *addtl)
+{
+ gpg_err_code_t ret = GPG_ERR_INV_ARG;
+
+ if (0 == buflen || !buf)
+ {
+ dbg (("DRBG: no buffer provided\n"));
+ return ret;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len)
+ {
+ dbg (("DRBG: wrong format of additional information\n"));
+ return ret;
+ }
+
+ /* 9.3.1 step 2 */
+ if (buflen > (drbg_max_request_bytes ()))
+ {
+ dbg (("DRBG: requested random numbers too large %u\n", buflen));
+ return ret;
+ }
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl ()))
+ {
+ dbg (("DRBG: additional information string too long %lu\n",
+ addtl->len));
+ return ret;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
+ * bit convoluted here, we make it simpler */
+ if ((drbg_max_requests ()) < drbg->reseed_ctr)
+ drbg->seeded = 0;
+
+ if (drbg->pr || !drbg->seeded)
+ {
+ dbg (("DRBG: reseeding before generation (prediction resistance: %s, state %s)\n", drbg->pr ? "true" : "false", drbg->seeded ? "seeded" : "unseeded"));
+ /* 9.3.1 steps 7.1 through 7.3 */
+ ret = drbg_seed (drbg, addtl, 1);
+ if (ret)
+ return ret;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+
+ if (addtl && addtl->buf)
+ {
+ dbg (("DRBG: using additional information string\n"));
+ }
+
+ /* 9.3.1 step 8 and 10 */
+ ret = drbg->d_ops->generate (drbg, buf, buflen, addtl);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ drbg->reseed_ctr++;
+ if (ret)
+ return ret;
+
+ /* 11.3.3 -- re-perform self tests after some generated random
+ * numbers, the chosen value after which self test is performed
+ * is arbitrary, but it should be reasonable */
+ /* Here we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the system integrity is violated.
+ * In this case, the entire system operation is questionable and it
+ * is unlikely that the integrity violation only affects to the
+ * correct operation of the DRBG.
+ */
+#if 0
+ if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096))
+ {
+ dbg (("DRBG: start to perform self test\n"));
+ ret = drbg_healthcheck ();
+ if (ret)
+ {
+ log_fatal (("DRBG: self test failed\n"));
+ return ret;
+ }
+ else
+ {
+ dbg (("DRBG: self test successful\n"));
+ }
+ }
+#endif
+
+ return ret;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static gpg_err_code_t
+drbg_generate_long (drbg_state_t drbg,
+ unsigned char *buf, unsigned int buflen,
+ drbg_string_t *addtl)
+{
+ gpg_err_code_t ret = 0;
+ unsigned int slice = 0;
+ unsigned char *buf_p = buf;
+ unsigned len = 0;
+ do
+ {
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes ());
+ chunk = slice ? drbg_max_request_bytes () : (buflen - len);
+ ret = drbg_generate (drbg, buf_p, chunk, addtl);
+ if (ret)
+ return ret;
+ buf_p += chunk;
+ len += chunk;
+ }
+ while (slice > 0 && (len < buflen));
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static gpg_err_code_t
+drbg_uninstantiate (drbg_state_t drbg)
+{
+ if (!drbg)
+ return GPG_ERR_INV_ARG;
+ drbg->d_ops->crypto_fini(drbg);
+ xfree (drbg->V);
+ drbg->V = NULL;
+ xfree (drbg->C);
+ drbg->C = NULL;
+ drbg->reseed_ctr = 0;
+ xfree (drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->seeded = 0;
+ drbg->pr = 0;
+ drbg->seed_init_pid = 0;
+ return 0;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @flags Flags defining the requested DRBG type and cipher type. The flags
+ * are defined in drbg.h and may be XORed. Beware, if you XOR multiple
+ * cipher types together, the code picks the core on a first come first
+ * serve basis as it iterates through the available cipher cores and
+ * uses the one with the first match. The minimum required flags are:
+ * cipher type flag
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static gpg_err_code_t
+drbg_instantiate (drbg_state_t drbg,
+ drbg_string_t *pers, int coreref, int pr)
+{
+ gpg_err_code_t ret = GPG_ERR_ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return GPG_ERR_INV_ARG;
+
+ dbg (("DRBG: Initializing DRBG core %d with prediction resistance %s\n",
+ coreref, pr ? "enabled" : "disabled"));
+ drbg->core = &drbg_cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = 0;
+ if (drbg->core->flags & DRBG_HMAC)
+ drbg->d_ops = &drbg_hmac_ops;
+ else if (drbg->core->flags & DRBG_HASH_MASK)
+ drbg->d_ops = &drbg_hash_ops;
+ else if (drbg->core->flags & DRBG_CTR_MASK)
+ drbg->d_ops = &drbg_ctr_ops;
+ else
+ return GPG_ERR_GENERAL;
+ /* 9.1 step 1 is implicit with the selected DRBG type -- see
+ * drbg_sec_strength() */
+
+ /* 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ ret = drbg->d_ops->crypto_init(drbg);
+ if (ret)
+ goto err;
+
+ drbg->V = xcalloc_secure (1, drbg_statelen (drbg));
+ if (!drbg->V)
+ goto fini;
+ drbg->C = xcalloc_secure (1, drbg_statelen (drbg));
+ if (!drbg->C)
+ goto fini;
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR_MASK)
+ sb_size = drbg_statelen (drbg) + drbg_blocklen (drbg) + /* temp */
+ drbg_statelen (drbg) + /* df_data */
+ drbg_blocklen (drbg) + /* pad */
+ drbg_blocklen (drbg) + /* iv */
+ drbg_statelen (drbg) + drbg_blocklen (drbg); /* temp */
+ else
+ sb_size = drbg_statelen (drbg);
+
+ if (0 < sb_size)
+ {
+ drbg->scratchpad = xcalloc_secure (1, sb_size);
+ if (!drbg->scratchpad)
+ goto fini;
+ }
+ dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size));
+
+ /* 9.1 step 6 through 11 */
+ ret = drbg_seed (drbg, pers, 0);
+ if (ret)
+ goto fini;
+
+ dbg (("DRBG: core %d %s prediction resistance successfully initialized\n",
+ coreref, pr ? "with" : "without"));
+ return 0;
+
+ fini:
+ drbg->d_ops->crypto_fini(drbg);
+ err:
+ drbg_uninstantiate (drbg);
+ return ret;
+}
+
+/*
+ * DRBG reseed function as required by SP800-90A
+ *
+ * @drbg DRBG state handle
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static gpg_err_code_t
+drbg_reseed (drbg_state_t drbg,drbg_string_t *addtl)
+{
+ gpg_err_code_t ret = 0;
+ ret = drbg_seed (drbg, addtl, 1);
+ return ret;
+}
+
+
+
+/******************************************************************
+ * Libgcrypt integration code.
+ ******************************************************************/
+
+/***************************************************
+ * Libgcrypt backend functions to the RNG API code.
+ ***************************************************/
+
+static inline void
+drbg_lock (void)
+{
+ gpg_err_code_t ec;
+
+ ec = gpgrt_lock_lock (&drbg_lock_var);
+ if (ec)
+ log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (ec));
+}
+
+static inline void
+drbg_unlock (void)
+{
+ gpg_err_code_t ec;
+
+ ec = gpgrt_lock_unlock (&drbg_lock_var);
+ if (ec)
+ log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (ec));
+}
+
+/* Basic initialization is required to initialize mutexes and
+ do a few checks on the implementation. */
+static void
+basic_initialization (void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ /* Make sure that we are still using the values we have
+ traditionally used for the random levels. */
+ gcry_assert (GCRY_WEAK_RANDOM == 0
+ && GCRY_STRONG_RANDOM == 1
+ && GCRY_VERY_STRONG_RANDOM == 2);
+}
+
+/****** helper functions where lock must be held by caller *****/
+
+/* Check whether given flags are known to point to an applicable DRBG */
+static gpg_err_code_t
+drbg_algo_available (u32 flags, int *coreref)
+{
+ int i = 0;
+ for (i = 0; ARRAY_SIZE (drbg_cores) > i; i++)
+ {
+ if ((drbg_cores[i].flags & DRBG_CIPHER_MASK) ==
+ (flags & DRBG_CIPHER_MASK))
+ {
+ *coreref = i;
+ return 0;
+ }
+ }
+ return GPG_ERR_GENERAL;
+}
+
+static gpg_err_code_t
+_drbg_init_internal (u32 flags, drbg_string_t *pers)
+{
+ static u32 oldflags;
+ gpg_err_code_t ret = 0;
+ int coreref = 0;
+ int pr = 0;
+
+ /* If a caller provides 0 as flags, use the flags of the previous
+ * initialization, otherwise use the current flags and remember them
+ * for the next invocation. If no flag is given and no global state
+ * is set this is the first initialization and we set the default
+ * type.
+ */
+ if (!flags && !drbg_state)
+ flags = oldflags = DRBG_DEFAULT_TYPE;
+ else if (!flags)
+ flags = oldflags;
+ else
+ oldflags = flags;
+
+ ret = drbg_algo_available (flags, &coreref);
+ if (ret)
+ return ret;
+
+ if (drbg_state)
+ {
+ drbg_uninstantiate (drbg_state);
+ }
+ else
+ {
+ drbg_state = xtrycalloc_secure (1, sizeof *drbg_state);
+ if (!drbg_state)
+ return gpg_err_code_from_syserror ();
+ }
+ if (flags & DRBG_PREDICTION_RESIST)
+ pr = 1;
+ ret = drbg_instantiate (drbg_state, pers, coreref, pr);
+ if (ret)
+ fips_signal_error ("DRBG cannot be initialized");
+ else
+ drbg_state->seed_init_pid = getpid ();
+ return ret;
+}
+
+/************* calls available to common RNG code **************/
+
+/*
+ * Initialize one DRBG invoked by the libgcrypt API
+ */
+void
+_gcry_rngdrbg_inititialize (int full)
+{
+ basic_initialization ();
+ if (!full)
+ return;
+ drbg_lock ();
+ if (!drbg_state)
+ _drbg_init_internal (0, NULL);
+ drbg_unlock ();
+}
+
+/*
+ * Backend handler function for GCRYCTL_DRBG_REINIT
+ *
+ * Select a different DRBG type and initialize it.
+ * Function checks whether requested DRBG type exists and returns an error in
+ * case it does not. In case of an error, the previous instantiated DRBG is
+ * left untouched and alive. Thus, in case of an error, a DRBG is always
+ * available, even if it is not the chosen one.
+ *
+ * Re-initialization will be performed in any case regardless whether flags
+ * or personalization string are set.
+ *
+ * If flags is NULL, do not change current DRBG. If PERS is NULL and
+ * NPERS is 0, re-initialize without personalization string. If PERS
+ * is not NULL NPERS must be one and PERS and the first ietm from the
+ * bufer is take as personalization string.
+ */
+gpg_err_code_t
+_gcry_rngdrbg_reinit (const char *flagstr, gcry_buffer_t *pers, int npers)
+{
+ gpg_err_code_t ret;
+ unsigned int flags;
+
+ /* If PERS is not given we expect NPERS to be zero; if given we
+ expect a one-item array. */
+ if ((!pers && npers) || (pers && npers != 1))
+ return GPG_ERR_INV_ARG;
+
+ ret = parse_flag_string (flagstr, &flags);
+ if (!ret)
+ {
+ dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags));
+ drbg_lock ();
+ if (pers)
+ {
+ drbg_string_t persbuf;
+
+ drbg_string_fill
+ (&persbuf, (const unsigned char *)pers[0].data + pers[0].off,
+ pers[0].len);
+ ret = _drbg_init_internal (flags, &persbuf);
+ }
+ else
+ ret = _drbg_init_internal (flags, NULL);
+ drbg_unlock ();
+ }
+ return ret;
+}
+
+/* Try to close the FDs of the random gather module. This is
+ * currently only implemented for rndlinux. */
+void
+_gcry_rngdrbg_close_fds (void)
+{
+#if USE_RNDLINUX
+ drbg_lock ();
+ _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
+ drbg_unlock ();
+#endif
+}
+
+/* Print some statistics about the RNG. */
+void
+_gcry_rngdrbg_dump_stats (void)
+{
+ /* Not yet implemented. */
+ /* Maybe dumping of reseed counter? */
+}
+
+/* This function returns true if no real RNG is available or the
+ * quality of the RNG has been degraded for test purposes. */
+int
+_gcry_rngdrbg_is_faked (void)
+{
+ return 0; /* Faked random is not allowed. */
+}
+
+/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
+ * should be in the range of 0..100 to indicate the goodness of the
+ * entropy added, or -1 for goodness not known. */
+gcry_error_t
+_gcry_rngdrbg_add_bytes (const void *buf, size_t buflen, int quality)
+{
+ gpg_err_code_t ret = 0;
+ drbg_string_t seed;
+ (void) quality;
+ _gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */
+ if (!drbg_state)
+ return GPG_ERR_GENERAL;
+ drbg_string_fill (&seed, (unsigned char *) buf, buflen);
+ drbg_lock ();
+ ret = drbg_reseed (drbg_state, &seed);
+ drbg_unlock ();
+ return ret;
+}
+
+/* This function is to be used for all types of random numbers, including
+ * nonces
+ */
+void
+_gcry_rngdrbg_randomize (void *buffer, size_t length,
+ enum gcry_random_level level)
+{
+ (void) level;
+ _gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */
+ drbg_lock ();
+ if (!drbg_state)
+ {
+ fips_signal_error ("DRBG is not initialized");
+ goto bailout;
+ }
+
+ /* As reseeding changes the entire state of the DRBG, including any
+ * key, either a re-init or a reseed is sufficient for a fork */
+ if (drbg_state->seed_init_pid != getpid ())
+ {
+ /* We are in a child of us. Perform a reseeding. */
+ if (drbg_reseed (drbg_state, NULL))
+ {
+ fips_signal_error ("reseeding upon fork failed");
+ log_fatal ("severe error getting random\n");
+ goto bailout;
+ }
+ }
+ /* potential integer overflow is covered by drbg_generate which
+ * ensures that length cannot overflow an unsigned int */
+ if (0 < length)
+ {
+ if (!buffer)
+ goto bailout;
+ if (drbg_generate_long (drbg_state, buffer, (unsigned int) length, NULL))
+ log_fatal ("No random numbers generated\n");
+ }
+ else
+ {
+ drbg_gen_t *data = (drbg_gen_t *)buffer;
+ /* catch NULL pointer */
+ if (!data || !data->outbuf)
+ {
+ fips_signal_error ("No output buffer provided");
+ goto bailout;
+ }
+ if (drbg_generate_long (drbg_state, data->outbuf, data->outlen,
+ data->addtl))
+ log_fatal ("No random numbers generated\n");
+ }
+
+ bailout:
+ drbg_unlock ();
+ return;
+
+}
+
+/***************************************************************
+ * Self-test code
+ ***************************************************************/
+
+/*
+ * Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ */
+struct gcry_drbg_test_vector drbg_test_pr[] = {
+ {
+ /* .flags = */ "sha256 pr" /* DRBG_PR_HASHSHA256 */,
+ /* .entropy = */ (unsigned char *)
+ "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
+ "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
+ "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
+ "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
+ /* .entropylen = */ 48,
+ /* .entpra = */ (unsigned char *)
+ "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
+ "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
+ "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
+ /* .entprb = */ (unsigned char *)
+ "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
+ "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
+ "\x76\xaa\x55\x04\x8b\x0a\x72\x95",
+ /* .entprlen = */ 32,
+ /* .addtla = */ (unsigned char *)
+ "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
+ "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
+ "\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
+ /* .addtlb = */ (unsigned char *)
+ "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
+ "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
+ "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
+ /* .addtllen = */ 32,
+ /* .pers = */ NULL,
+ /* .perslen = */ 0,
+ /* .expected = */ (unsigned char *)
+ "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
+ "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
+ "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
+ "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
+ "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
+ "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
+ "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
+ "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
+ "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
+ "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
+ "\x50\x47\xa3\x63\x81\x16\xaf\x19",
+ /* .expectedlen = */ 128,
+ /* .entropyreseed = */ NULL,
+ /* .entropyreseed_len = */ 0,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ },
+ {
+ /* flags = */ "hmac sha256 pr" /* DRBG_PR_HMACSHA256 */,
+ /* .entropy = */ (unsigned char *)
+ "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
+ "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
+ "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
+ "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
+ /* .entropylen = */ 48,
+ /* .entpra = */ (unsigned char *)
+ "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
+ "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
+ "\x20\x28\xad\xf2\x60\xd7\xcd\x45",
+ /* .entprb = */ (unsigned char *)
+ "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
+ "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
+ "\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
+ /* .entprlen = */ 32,
+ /* .addtla = */ NULL,
+ /* .addtlb = */ NULL,
+ /* .addtllen = */ 0,
+ /* .pers = */ (unsigned char *)
+ "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
+ "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
+ "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
+ /* .perslen = */ 32,
+ /* .expected = */ (unsigned char *)
+ "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
+ "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
+ "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
+ "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
+ "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
+ "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
+ "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
+ "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
+ "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
+ "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
+ "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
+ /* .expectedlen = */ 128,
+ /* .entropyreseed = */ NULL,
+ /* .entropyreseed_len = */ 0,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ },
+ {
+ /* .flags = */ "aes sym128 pr", /* DRBG_PR_CTRAES128 */
+ /* .entropy = */ (unsigned char *)
+ "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
+ "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
+ /* .entropylen = */ 24,
+ /* .entpra = */ (unsigned char *)
+ "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
+ "\xc4\x2c\xe8\x10",
+ /* .entprb = */ (unsigned char *)
+ "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
+ "\x08\xf7\xa5\x01",
+ /* .entprlen = */ 16,
+ /* .addtla = */ (unsigned char *)
+ "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
+ "\x23\x6d\xad\x1d",
+ /* .addtlb = */ (unsigned char *)
+ "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
+ "\xbc\x59\x31\x8c",
+ /* .addtllen = */ 16,
+ /* .pers = */ (unsigned char *)
+ "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
+ "\x37\x3c\x5c\x0b",
+ /* .perslen = */ 16,
+ /* .expected = */ (unsigned char *)
+ "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
+ "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
+ "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
+ "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
+ "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
+ "\x23\xc5\x1f\x68",
+ /* .expectedlen = */ 64,
+ /* .entropyreseed = */ NULL,
+ /* .entropyreseed_len = */ 0,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ }
+};
+
+struct gcry_drbg_test_vector drbg_test_nopr[] = {
+ {
+ /* .flags = */ "sha256" /* DRBG_NOPR_HASHSHA256 */,
+ /* .entropy = */ (unsigned char *)
+ "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
+ "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
+ "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
+ "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
+ /* .entropylen = */ 48,
+ /* .entpra = */ NULL,
+ /* .entprb = */ NULL,
+ /* .entprlen = */ 0,
+ /* .addtla = */ (unsigned char *)
+ "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
+ "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
+ "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
+ /* .addtlb = */ (unsigned char *)
+ "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
+ "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
+ "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
+ /* .addtllen = */ 32,
+ /* .pers = */ NULL,
+ /* .perslen = */ 0,
+ /* .expected = */ (unsigned char *)
+ "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
+ "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
+ "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
+ "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
+ "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
+ "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
+ "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
+ "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
+ "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
+ "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
+ "\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
+ /* .expectedlen = */ 128,
+ /* .entropyreseed = */ NULL,
+ /* .entropyreseed_len = */ 0,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ },
+ {
+ /* .flags = */ "hmac sha256" /* DRBG_NOPR_HMACSHA256 */,
+ /* .entropy = */ (unsigned char *)
+ "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
+ "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
+ "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
+ "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
+ /* .entropylen = */ 48,
+ /* .entpra = */ NULL,
+ /* .entprb = */ NULL,
+ /* .entprlen = */ 0,
+ /* .addtla = */ NULL,
+ /* .addtlb = */ NULL,
+ /* .addtllen = */ 0,
+ /* .pers = */ (unsigned char *)
+ "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
+ "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
+ "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
+ /* .perslen = */ 32,
+ /* .expected = */ (unsigned char *)
+ "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
+ "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
+ "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
+ "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
+ "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
+ "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
+ "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
+ "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
+ "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
+ "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
+ "\x10\x37\x41\x03\x0c\xcc\x3a\x56",
+ /* .expectedlen = */ 128,
+ /* .entropyreseed = */ NULL,
+ /* .entropyreseed_len = */ 0,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ },
+ {
+ /* .flags = */ "aes sym128" /* DRBG_NOPR_CTRAES128 */,
+ /* .entropy = */ (unsigned char *)
+ "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
+ "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
+ /* .entropylen = */ 24,
+ /* .entpra = */ NULL,
+ /* .entprb = */ NULL,
+ /* .entprlen = */ 0,
+ /* .addtla = */ (unsigned char *)
+ "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
+ "\x44\x85\xe7\xfe",
+ /* .addtlb = */ (unsigned char *)
+ "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
+ "\x82\x16\x62\x7f",
+ /* .addtllen = */ 16,
+ /* .pers = */ (unsigned char *)
+ "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
+ "\x8e\xcf\xe0\x02",
+ /* .perslen = */ 16,
+ /* .expected = */ (unsigned char *)
+ "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
+ "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
+ "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
+ "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
+ "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
+ "\x2b\x49\x1e\x5c",
+ /* .expectedlen = */ 64,
+ /* .entropyreseed = */ NULL,
+ /* .entropyreseed_len = */ 0,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ },
+ {
+ /* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */,
+ /* .entropy = */ (unsigned char *)
+ "\x16\x10\xb8\x28\xcc\xd2\x7d\xe0\x8c\xee\xa0\x32"
+ "\xa2\x0e\x92\x08\x49\x2c\xf1\x70\x92\x42\xf6\xb5",
+ /* .entropylen = */ 24,
+ /* .entpra = */ NULL,
+ /* .entprb = */ NULL,
+ /* .entprlen = */ 0,
+ /* .addtla = */ NULL,
+ /* .addtlb = */ NULL,
+ /* .addtllen = */ 0,
+ /* .pers = */ NULL,
+ /* .perslen = */ 0,
+ /* .expected = */ (unsigned char *)
+ "\x56\xf3\x3d\x4f\xdb\xb9\xa5\xb6\x4d\x26\x23\x44"
+ "\x97\xe9\xdc\xb8\x77\x98\xc6\x8d\x08\xf7\xc4\x11"
+ "\x99\xd4\xbd\xdf\x97\xeb\xbf\x6c\xb5\x55\x0e\x5d"
+ "\x14\x9f\xf4\xd5\xbd\x0f\x05\xf2\x5a\x69\x88\xc1"
+ "\x74\x36\x39\x62\x27\x18\x4a\xf8\x4a\x56\x43\x35"
+ "\x65\x8e\x2f\x85\x72\xbe\xa3\x33\xee\xe2\xab\xff"
+ "\x22\xff\xa6\xde\x3e\x22\xac\xa2",
+ /* .expectedlen = */ 80,
+ /* .entropyreseed = */ (unsigned char *)
+ "\x72\xd2\x8c\x90\x8e\xda\xf9\xa4\xd1\xe5\x26\xd8"
+ "\xf2\xde\xd5\x44",
+ /* .entropyreseed_len = */ 16,
+ /* .addtl_reseed = */ NULL,
+ /* .addtl_reseed_len = */ 0
+ },
+ {
+ /* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */,
+ /* .entropy = */ (unsigned char *)
+ "\xd9\xba\xb5\xce\xdc\xa9\x6f\x61\x78\xd6\x45\x09"
+ "\xa0\xdf\xdc\x5e\xda\xd8\x98\x94\x14\x45\x0e\x01",
+ /* .entropylen = */ 24,
+ /* .entpra = */ NULL,
+ /* .entprb = */ NULL,
+ /* .entprlen = */ 0,
+ /* .addtla = */ (unsigned char *)
+ "\x04\xfa\x28\x95\xaa\x5a\x6f\x8c\x57\x43\x34\x3b"
+ "\x80\x5e\x5e\xa4",
+ /* .addtlb = */ (unsigned char *)
+ "\xdf\x5d\xc4\x59\xdf\xf0\x2a\xa2\xf0\x52\xd7\x21"
+ "\xec\x60\x72\x30",
+ /* .addtllen = */ 16,
+ /* .pers = */ NULL,
+ /* .perslen = */ 0,
+ /* .expected = */ (unsigned char *)
+ "\xc4\x8b\x89\xf9\xda\x3f\x74\x82\x45\x55\x5d\x5d"
+ "\x03\x3b\x69\x3d\xd7\x1a\x4d\xf5\x69\x02\x05\xce"
+ "\xfc\xd7\x20\x11\x3c\xc2\x4e\x09\x89\x36\xff\x5e"
+ "\x77\xb5\x41\x53\x58\x70\xb3\x39\x46\x8c\xdd\x8d"
+ "\x6f\xaf\x8c\x56\x16\x3a\x70\x0a\x75\xb2\x3e\x59"
+ "\x9b\x5a\xec\xf1\x6f\x3b\xaf\x6d\x5f\x24\x19\x97"
+ "\x1f\x24\xf4\x46\x72\x0f\xea\xbe",
+ /* .expectedlen = */ 80,
+ /* .entropyreseed = */ (unsigned char *)
+ "\xc6\xba\xd0\x74\xc5\x90\x67\x86\xf5\xe1\xf3\x20"
+ "\x99\xf5\xb4\x91",
+ /* .entropyreseed_len = */ 16,
+ /* .addtl_reseed = */ (unsigned char *)
+ "\x3e\x6b\xf4\x6f\x4d\xaa\x38\x25\xd7\x19\x4e\x69"
+ "\x4e\x77\x52\xf7",
+ /* .addtl_reseed_len = */ 16
+ }
+};
+
+
+/*
+ * Tests implement the CAVS test approach as documented in
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf
+ */
+
+/*
+ * CAVS test
+ *
+ * This function is not static as it is needed for as a private API
+ * call for the CAVS test tool.
+ */
+gpg_err_code_t
+_gcry_rngdrbg_cavs_test (struct gcry_drbg_test_vector *test, unsigned char *buf)
+{
+ gpg_err_code_t ret = 0;
+ drbg_state_t drbg = NULL;
+ struct drbg_test_data_s test_data;
+ drbg_string_t addtl, pers, testentropy;
+ int coreref = 0;
+ int pr = 0;
+ u32 flags;
+
+ ret = parse_flag_string (test->flagstr, &flags);
+ if (ret)
+ goto outbuf;
+
+ ret = drbg_algo_available (flags, &coreref);
+ if (ret)
+ goto outbuf;
+
+ drbg = xtrycalloc_secure (1, sizeof *drbg);
+ if (!drbg)
+ {
+ ret = gpg_err_code_from_syserror ();
+ goto outbuf;
+ }
+
+ if ((flags & DRBG_PREDICTION_RESIST))
+ pr = 1;
+
+ test_data.testentropy = &testentropy;
+ drbg_string_fill (&testentropy, test->entropy, test->entropylen);
+ drbg->test_data = &test_data;
+ drbg_string_fill (&pers, test->pers, test->perslen);
+ ret = drbg_instantiate (drbg, &pers, coreref, pr);
+ if (ret)
+ goto outbuf;
+
+ if (test->entropyreseed)
+ {
+ drbg_string_fill (&testentropy, test->entropyreseed,
+ test->entropyreseed_len);
+ drbg_string_fill (&addtl, test->addtl_reseed,
+ test->addtl_reseed_len);
+ if (drbg_reseed (drbg, &addtl))
+ goto outbuf;
+ }
+
+ drbg_string_fill (&addtl, test->addtla, test->addtllen);
+ if (test->entpra)
+ {
+ drbg_string_fill (&testentropy, test->entpra, test->entprlen);
+ drbg->test_data = &test_data;
+ }
+ drbg_generate_long (drbg, buf, test->expectedlen, &addtl);
+
+ drbg_string_fill (&addtl, test->addtlb, test->addtllen);
+ if (test->entprb)
+ {
+ drbg_string_fill (&testentropy, test->entprb, test->entprlen);
+ drbg->test_data = &test_data;
+ }
+ drbg_generate_long (drbg, buf, test->expectedlen, &addtl);
+ drbg_uninstantiate (drbg);
+
+ outbuf:
+ xfree (drbg);
+ return ret;
+}
+
+/*
+ * Invoke the CAVS test and perform the final check whether the
+ * calculated random value matches the expected one.
+ *
+ * This function is not static as it is needed for as a private API
+ * call for the CAVS test tool.
+ */
+gpg_err_code_t
+_gcry_rngdrbg_healthcheck_one (struct gcry_drbg_test_vector * test)
+{
+ gpg_err_code_t ret = GPG_ERR_ENOMEM;
+ unsigned char *buf = xcalloc_secure (1, test->expectedlen);
+ if (!buf)
+ return GPG_ERR_ENOMEM;
+
+ ret = _gcry_rngdrbg_cavs_test (test, buf);
+ /* FIXME: The next line is wrong. */
+ ret = memcmp (test->expected, buf, test->expectedlen);
+
+ xfree (buf);
+ return ret;
+}
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note, testing the reseed counter is not done as an automatic reseeding
+ * is performed in drbg_generate when the reseed counter is too large.
+ */
+static gpg_err_code_t
+drbg_healthcheck_sanity (struct gcry_drbg_test_vector *test)
+{
+ unsigned int len = 0;
+ drbg_state_t drbg = NULL;
+ gpg_err_code_t ret = GPG_ERR_GENERAL;
+ gpg_err_code_t tmpret = GPG_ERR_GENERAL;
+ struct drbg_test_data_s test_data;
+ drbg_string_t addtl, testentropy;
+ int coreref = 0;
+ unsigned char *buf = NULL;
+ size_t max_addtllen, max_request_bytes;
+ u32 flags;
+
+ /* only perform test in FIPS mode */
+ if (0 == fips_mode ())
+ return 0;
+
+ ret = parse_flag_string (test->flagstr, &flags);
+ if (ret)
+ return ret;
+ ret = GPG_ERR_GENERAL; /* Fixme: Improve handling of RET. */
+
+ buf = xtrycalloc_secure (1, test->expectedlen);
+ if (!buf)
+ return gpg_err_code_from_syserror ();
+ tmpret = drbg_algo_available (flags, &coreref);
+ if (tmpret)
+ goto outbuf;
+ drbg = xtrycalloc_secure (1, sizeof *drbg);
+ if (!drbg)
+ {
+ ret = gpg_err_code_from_syserror ();
+ goto outbuf;
+ }
+
+ /* if the following tests fail, it is likely that there is a buffer
+ * overflow and we get a SIGSEV */
+ ret = drbg_instantiate (drbg, NULL, coreref, 1);
+ if (ret)
+ goto outbuf;
+ max_addtllen = drbg_max_addtl ();
+ max_request_bytes = drbg_max_request_bytes ();
+ /* overflow addtllen with additional info string */
+ drbg_string_fill (&addtl, test->addtla, (max_addtllen + 1));
+ len = drbg_generate (drbg, buf, test->expectedlen, &addtl);
+ if (len)
+ goto outdrbg;
+
+ /* overflow max_bits */
+ len = drbg_generate (drbg, buf, (max_request_bytes + 1), NULL);
+ if (len)
+ goto outdrbg;
+ drbg_uninstantiate (drbg);
+
+ /* test failing entropy source as defined in 11.3.2 */
+ test_data.testentropy = NULL;
+ test_data.fail_seed_source = 1;
+ drbg->test_data = &test_data;
+ tmpret = drbg_instantiate (drbg, NULL, coreref, 0);
+ if (!tmpret)
+ goto outdrbg;
+ test_data.fail_seed_source = 0;
+
+ test_data.testentropy = &testentropy;
+ drbg_string_fill (&testentropy, test->entropy, test->entropylen);
+ /* overflow max addtllen with personalization string */
+ tmpret = drbg_instantiate (drbg, &addtl, coreref, 0);
+ if (!tmpret)
+ goto outdrbg;
+
+ dbg (("DRBG: Sanity tests for failure code paths successfully completed\n"));
+ ret = 0;
+
+ outdrbg:
+ drbg_uninstantiate (drbg);
+ outbuf:
+ xfree (buf);
+ xfree (drbg);
+ return ret;
+}
+
+/*
+ * DRBG Healthcheck function as required in SP800-90A
+ *
+ * return:
+ * 0 on success (all tests pass)
+ * >0 on error (return code indicate the number of failures)
+ */
+static int
+drbg_healthcheck (void)
+{
+ int ret = 0;
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[0]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[1]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[2]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[3]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[4]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[0]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[1]);
+ ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[2]);
+ ret += drbg_healthcheck_sanity (&drbg_test_nopr[0]);
+ return ret;
+}
+
+/* Run the self-tests. */
+gcry_error_t
+_gcry_rngdrbg_selftest (selftest_report_func_t report)
+{
+ gcry_err_code_t ec;
+ const char *errtxt = NULL;
+ drbg_lock ();
+ if (0 != drbg_healthcheck ())
+ errtxt = "RNG output does not match known value";
+ drbg_unlock ();
+ if (report && errtxt)
+ report ("random", 0, "KAT", errtxt);
+ ec = errtxt ? GPG_ERR_SELFTEST_FAILED : 0;
+ return gpg_error (ec);
+}
+
+/***************************************************************
+ * Cipher invocations requested by DRBG
+ ***************************************************************/
+
+static gpg_err_code_t
+drbg_hash_init (drbg_state_t drbg)
+{
+ gcry_md_hd_t hd;
+ gpg_error_t err;
+
+ err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0);
+ if (err)
+ return err;
+
+ drbg->priv_data = hd;
+
+ return 0;
+}
+
+static gpg_err_code_t
+drbg_hmac_init (drbg_state_t drbg)
+{
+ gcry_md_hd_t hd;
+ gpg_error_t err;
+
+ err = _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC);
+ if (err)
+ return err;
+
+ drbg->priv_data = hd;
+
+ return 0;
+}
+
+static gpg_err_code_t
+drbg_hmac_setkey (drbg_state_t drbg, const unsigned char *key)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
+
+ return _gcry_md_setkey (hd, key, drbg_statelen (drbg));
+}
+
+static void
+drbg_hash_fini (drbg_state_t drbg)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
+
+ _gcry_md_close (hd);
+}
+
+static byte *
+drbg_hash (drbg_state_t drbg, const drbg_string_t *buf)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
+
+ _gcry_md_reset(hd);
+ for (; NULL != buf; buf = buf->next)
+ _gcry_md_write (hd, buf->buf, buf->len);
+ _gcry_md_final (hd);
+ return _gcry_md_read (hd, drbg->core->backend_cipher);
+}
+
+static void
+drbg_sym_fini (drbg_state_t drbg)
+{
+ gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
+
+ if (hd)
+ _gcry_cipher_close (hd);
+ if (drbg->ctr_handle)
+ _gcry_cipher_close (drbg->ctr_handle);
+}
+
+static gpg_err_code_t
+drbg_sym_init (drbg_state_t drbg)
+{
+ gcry_cipher_hd_t hd;
+ gpg_error_t err;
+
+ err = _gcry_cipher_open (&hd, drbg->core->backend_cipher,
+ GCRY_CIPHER_MODE_ECB, 0);
+ if (err)
+ {
+ drbg_sym_fini (drbg);
+ return err;
+ }
+ drbg->priv_data = hd;
+
+ err = _gcry_cipher_open (&drbg->ctr_handle, drbg->core->backend_cipher,
+ GCRY_CIPHER_MODE_CTR, 0);
+ if (err)
+ {
+ drbg_sym_fini (drbg);
+ return err;
+ }
+
+
+ if (drbg_blocklen (drbg) !=
+ _gcry_cipher_get_algo_blklen (drbg->core->backend_cipher))
+ {
+ drbg_sym_fini (drbg);
+ return -GPG_ERR_NO_ERROR;
+ }
+
+ return 0;
+}
+
+static gpg_err_code_t
+drbg_sym_setkey (drbg_state_t drbg, const unsigned char *key)
+{
+ gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
+
+ return _gcry_cipher_setkey (hd, key, drbg_keylen (drbg));
+}
+
+static gpg_err_code_t
+drbg_sym (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf)
+{
+ gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
+
+ _gcry_cipher_reset(hd);
+ if (drbg_blocklen (drbg) < buf->len)
+ return -GPG_ERR_NO_ERROR;
+ /* in is only component */
+ return _gcry_cipher_encrypt (hd, outval, drbg_blocklen (drbg), buf->buf,
+ buf->len);
+}
+
+static gpg_err_code_t
+drbg_sym_ctr (drbg_state_t drbg,
+ const unsigned char *inbuf, unsigned int inbuflen,
+ unsigned char *outbuf, unsigned int outbuflen)
+{
+ gpg_error_t err;
+
+ _gcry_cipher_reset(drbg->ctr_handle);
+ err = _gcry_cipher_setctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg));
+ if (err)
+ return err;
+
+ while (outbuflen)
+ {
+ unsigned int cryptlen = (inbuflen > outbuflen) ? outbuflen : inbuflen;
+
+ err = _gcry_cipher_encrypt (drbg->ctr_handle, outbuf, cryptlen, inbuf,
+ cryptlen);
+ if (err)
+ return err;
+
+ outbuflen -= cryptlen;
+ outbuf += cryptlen;
+ }
+ return _gcry_cipher_getctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg));
+}
diff --git a/comm/third_party/libgcrypt/random/random-system.c b/comm/third_party/libgcrypt/random/random-system.c
new file mode 100644
index 0000000000..8b79511c64
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/random-system.c
@@ -0,0 +1,250 @@
+/* random-system.c - wrapper around the system's RNG
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ This RNG is merely wrapper around the system's native RNG. For
+ example on Unix systems it directly uses /dev/{u,}random.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+
+#include "g10lib.h"
+#include "random.h"
+#include "rand-internal.h"
+
+/* This is the lock we use to serialize access to this RNG. The extra
+ integer variable is only used to check the locking state; that is,
+ it is not meant to be thread-safe but merely as a failsafe feature
+ to assert proper locking. */
+GPGRT_LOCK_DEFINE (system_rng_lock);
+static int system_rng_is_locked;
+
+
+/* --- Local prototypes --- */
+
+
+
+
+/* --- Functions --- */
+
+/* Basic initialization is required to initialize mutexes and
+ do a few checks on the implementation. */
+static void
+basic_initialization (void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ system_rng_is_locked = 0;
+
+ /* Make sure that we are still using the values we traditionally
+ used for the random levels. */
+ gcry_assert (GCRY_WEAK_RANDOM == 0
+ && GCRY_STRONG_RANDOM == 1
+ && GCRY_VERY_STRONG_RANDOM == 2);
+
+}
+
+
+/* Acquire the system_rng_lock. */
+static void
+lock_rng (void)
+{
+ gpg_err_code_t rc;
+
+ rc = gpgrt_lock_lock (&system_rng_lock);
+ if (rc)
+ log_fatal ("failed to acquire the System RNG lock: %s\n",
+ gpg_strerror (rc));
+ system_rng_is_locked = 1;
+}
+
+
+/* Release the system_rng_lock. */
+static void
+unlock_rng (void)
+{
+ gpg_err_code_t rc;
+
+ system_rng_is_locked = 0;
+ rc = gpgrt_lock_unlock (&system_rng_lock);
+ if (rc)
+ log_fatal ("failed to release the System RNG lock: %s\n",
+ gpg_strerror (rc));
+}
+
+
+/* Helper variables for read_cb().
+
+ The _gcry_rnd*_gather_random interface does not allow to provide a
+ data pointer. Thus we need to use a global variable for
+ communication. However, the then required locking is anyway a good
+ idea because it does not make sense to have several readers of (say
+ /dev/random). It is easier to serve them one after the other. */
+static unsigned char *read_cb_buffer; /* The buffer. */
+static size_t read_cb_size; /* Size of the buffer. */
+static size_t read_cb_len; /* Used length. */
+
+
+/* Callback for _gcry_rnd*_gather_random. */
+static void
+read_cb (const void *buffer, size_t length, enum random_origins origin)
+{
+ const unsigned char *p = buffer;
+
+ (void)origin;
+
+ gcry_assert (system_rng_is_locked);
+ gcry_assert (read_cb_buffer);
+
+ /* Note that we need to protect against gatherers returning more
+ than the requested bytes (e.g. rndw32). */
+ while (length-- && read_cb_len < read_cb_size)
+ {
+ read_cb_buffer[read_cb_len++] = *p++;
+ }
+}
+
+
+/* Fill BUFFER with LENGTH bytes of random at quality LEVEL. The
+ function either succeeds or terminates the process in case of a
+ fatal error. */
+static void
+get_random (void *buffer, size_t length, int level)
+{
+ int rc;
+
+ gcry_assert (buffer);
+
+ read_cb_buffer = buffer;
+ read_cb_size = length;
+ read_cb_len = 0;
+
+#if USE_RNDLINUX
+ rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level);
+#elif USE_RNDUNIX
+ rc = _gcry_rndunix_gather_random (read_cb, 0, length, level);
+#elif USE_RNDW32
+ do
+ {
+ rc = _gcry_rndw32_gather_random (read_cb, 0, length, level);
+ }
+ while (rc >= 0 && read_cb_len < read_cb_size);
+#else
+ rc = -1;
+#endif
+
+ if (rc < 0 || read_cb_len != read_cb_size)
+ {
+ log_fatal ("error reading random from system RNG (rc=%d)\n", rc);
+ }
+}
+
+
+
+/* --- Public Functions --- */
+
+/* Initialize this random subsystem. If FULL is false, this function
+ merely calls the basic initialization of the module and does not do
+ anything more. Doing this is not really required but when running
+ in a threaded environment we might get a race condition
+ otherwise. */
+void
+_gcry_rngsystem_initialize (int full)
+{
+ basic_initialization ();
+ if (!full)
+ return;
+ /* Nothing more to initialize. */
+ return;
+}
+
+
+/* Try to close the FDs of the random gather module. This is
+ currently only implemented for rndlinux. */
+void
+_gcry_rngsystem_close_fds (void)
+{
+ lock_rng ();
+#if USE_RNDLINUX
+ _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
+#endif
+ unlock_rng ();
+}
+
+
+/* Print some statistics about the RNG. */
+void
+_gcry_rngsystem_dump_stats (void)
+{
+ /* Not yet implemented. */
+}
+
+
+/* This function returns true if no real RNG is available or the
+ quality of the RNG has been degraded for test purposes. */
+int
+_gcry_rngsystem_is_faked (void)
+{
+ return 0; /* Faked random is not supported. */
+}
+
+
+/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
+ should be in the range of 0..100 to indicate the goodness of the
+ entropy added, or -1 for goodness not known. */
+gcry_error_t
+_gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality)
+{
+ (void)buf;
+ (void)buflen;
+ (void)quality;
+ return 0; /* Not implemented. */
+}
+
+
+/* Public function to fill the buffer with LENGTH bytes of
+ cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
+ here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong
+ enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key
+ generation stuff but may be very slow. */
+void
+_gcry_rngsystem_randomize (void *buffer, size_t length,
+ enum gcry_random_level level)
+{
+ _gcry_rngsystem_initialize (1); /* Auto-initialize if needed. */
+
+ if (level != GCRY_VERY_STRONG_RANDOM)
+ level = GCRY_STRONG_RANDOM;
+
+ lock_rng ();
+ get_random (buffer, length, level);
+ unlock_rng ();
+}
diff --git a/comm/third_party/libgcrypt/random/random.c b/comm/third_party/libgcrypt/random/random.c
new file mode 100644
index 0000000000..9aab78930b
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/random.c
@@ -0,0 +1,584 @@
+/* random.c - Random number switch
+ * Copyright (C) 2003, 2006, 2008, 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ This module switches between different implementations of random
+ number generators and provides a few help functions.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_SYSLOG
+# include <syslog.h>
+#endif /*HAVE_SYSLOG*/
+#include <ctype.h>
+
+#include "g10lib.h"
+#include "random.h"
+#include "rand-internal.h"
+#include "cipher.h" /* For _gcry_sha1_hash_buffer(). */
+
+/* The name of a file used to globally configure the RNG. */
+#define RANDOM_CONF_FILE "/etc/gcrypt/random.conf"
+
+
+/* If not NULL a progress function called from certain places and the
+ opaque value passed along. Registered by
+ _gcry_register_random_progress (). */
+static void (*progress_cb) (void *,const char*,int,int, int );
+static void *progress_cb_data;
+
+/* Flags indicating the requested RNG types. */
+static struct
+{
+ int standard;
+ int fips;
+ int system;
+} rng_types;
+
+
+/* This is the lock we use to protect the buffer used by the nonce
+ generation. */
+GPGRT_LOCK_DEFINE (nonce_buffer_lock);
+
+
+
+/* --- Functions --- */
+
+
+/* Used to register a progress callback. This needs to be called
+ before any threads are created. */
+void
+_gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
+ void *cb_data )
+{
+ progress_cb = cb;
+ progress_cb_data = cb_data;
+}
+
+
+/* This progress function is currently used by the random modules to
+ give hints on how much more entropy is required. */
+void
+_gcry_random_progress (const char *what, int printchar, int current, int total)
+{
+ if (progress_cb)
+ progress_cb (progress_cb_data, what, printchar, current, total);
+}
+
+
+/* Read a file with configure options. The file is a simple text file
+ * where empty lines and lines with the first non white-space
+ * character being '#' are ignored. Supported configure options are:
+ *
+ * disable-jent - Disable the jitter based extra entropy generator.
+ * This sets the RANDOM_CONF_DISABLE_JENT bit.
+ * only-urandom - Always use /dev/urandom instead of /dev/random.
+ * This sets the RANDOM_CONF_ONLY_URANDOM bit.
+ *
+ * The function returns a bit vector with flags read from the file.
+ */
+unsigned int
+_gcry_random_read_conf (void)
+{
+ const char *fname = RANDOM_CONF_FILE;
+ FILE *fp;
+ char buffer[256];
+ char *p, *pend;
+ int lnr = 0;
+ unsigned int result = 0;
+
+ fp = fopen (fname, "r");
+ if (!fp)
+ return result;
+
+ for (;;)
+ {
+ if (!fgets (buffer, sizeof buffer, fp))
+ {
+ if (!feof (fp))
+ {
+#ifdef HAVE_SYSLOG
+ syslog (LOG_USER|LOG_WARNING,
+ "Libgcrypt warning: error reading '%s', line %d",
+ fname, lnr);
+#endif /*HAVE_SYSLOG*/
+ }
+ fclose (fp);
+ return result;
+ }
+ lnr++;
+ for (p=buffer; my_isascii (*p) && isspace (*p); p++)
+ ;
+ pend = strchr (p, '\n');
+ if (pend)
+ *pend = 0;
+ pend = p + (*p? (strlen (p)-1):0);
+ for ( ;pend > p; pend--)
+ if (my_isascii (*pend) && isspace (*pend))
+ *pend = 0;
+ if (!*p || *p == '#')
+ continue;
+
+ if (!strcmp (p, "disable-jent"))
+ result |= RANDOM_CONF_DISABLE_JENT;
+ else if (!strcmp (p, "only-urandom"))
+ result |= RANDOM_CONF_ONLY_URANDOM;
+ else
+ {
+#ifdef HAVE_SYSLOG
+ syslog (LOG_USER|LOG_WARNING,
+ "Libgcrypt warning: unknown option in '%s', line %d",
+ fname, lnr);
+#endif /*HAVE_SYSLOG*/
+ }
+ }
+}
+
+
+/* Set the preferred RNG type. This may be called at any time even
+ before gcry_check_version. Thus we can't assume any thread system
+ initialization. A type of 0 is used to indicate that any Libgcrypt
+ initialization has been done.*/
+void
+_gcry_set_preferred_rng_type (int type)
+{
+ static int any_init;
+
+ if (!type)
+ {
+ any_init = 1;
+ }
+ else if (type == GCRY_RNG_TYPE_STANDARD)
+ {
+ rng_types.standard = 1;
+ }
+ else if (any_init)
+ {
+ /* After any initialization has been done we only allow to
+ upgrade to the standard RNG (handled above). All other
+ requests are ignored. The idea is that the application needs
+ to declare a preference for a weaker RNG as soon as possible
+ and before any library sets a preference. We assume that a
+ library which uses Libgcrypt calls an init function very
+ early. This way --- even if the library gets initialized
+ early by the application --- it is unlikely that it can
+ select a lower priority RNG.
+
+ This scheme helps to ensure that existing unmodified
+ applications (e.g. gpg2), which don't known about the new RNG
+ selection system, will continue to use the standard RNG and
+ not be tricked by some library to use a lower priority RNG.
+ There are some loopholes here but at least most GnuPG stuff
+ should be save because it calls src_c{gcry_control
+ (GCRYCTL_SUSPEND_SECMEM_WARN);} quite early and thus inhibits
+ switching to a low priority RNG.
+ */
+ }
+ else if (type == GCRY_RNG_TYPE_FIPS)
+ {
+ rng_types.fips = 1;
+ }
+ else if (type == GCRY_RNG_TYPE_SYSTEM)
+ {
+ rng_types.system = 1;
+ }
+}
+
+
+/* Initialize this random subsystem. If FULL is false, this function
+ merely calls the basic initialization of the module and does not do
+ anything more. Doing this is not really required but when running
+ in a threaded environment we might get a race condition
+ otherwise. */
+void
+_gcry_random_initialize (int full)
+{
+ if (fips_mode ())
+ _gcry_rngdrbg_inititialize (full);
+ else if (rng_types.standard)
+ _gcry_rngcsprng_initialize (full);
+ else if (rng_types.fips)
+ _gcry_rngdrbg_inititialize (full);
+ else if (rng_types.system)
+ _gcry_rngsystem_initialize (full);
+ else
+ _gcry_rngcsprng_initialize (full);
+}
+
+
+/* If possible close file descriptors used by the RNG. */
+void
+_gcry_random_close_fds (void)
+{
+ /* Note that we can't do that directly because each random system
+ has its own lock functions which need to be used for accessing
+ the entropy gatherer. */
+
+ if (fips_mode ())
+ _gcry_rngdrbg_close_fds ();
+ else if (rng_types.standard)
+ _gcry_rngcsprng_close_fds ();
+ else if (rng_types.fips)
+ _gcry_rngdrbg_close_fds ();
+ else if (rng_types.system)
+ _gcry_rngsystem_close_fds ();
+ else
+ _gcry_rngcsprng_close_fds ();
+}
+
+
+/* Return the current RNG type. IGNORE_FIPS_MODE is a flag used to
+ skip the test for FIPS. This is useful, so that we are able to
+ return the type of the RNG even before we have setup FIPS mode
+ (note that FIPS mode is enabled by default until it is switched off
+ by the initialization). This is mostly useful for the regression
+ test. */
+int
+_gcry_get_rng_type (int ignore_fips_mode)
+{
+ if (!ignore_fips_mode && fips_mode ())
+ return GCRY_RNG_TYPE_FIPS;
+ else if (rng_types.standard)
+ return GCRY_RNG_TYPE_STANDARD;
+ else if (rng_types.fips)
+ return GCRY_RNG_TYPE_FIPS;
+ else if (rng_types.system)
+ return GCRY_RNG_TYPE_SYSTEM;
+ else
+ return GCRY_RNG_TYPE_STANDARD;
+}
+
+
+void
+_gcry_random_dump_stats (void)
+{
+ if (fips_mode ())
+ _gcry_rngdrbg_dump_stats ();
+ else
+ _gcry_rngcsprng_dump_stats ();
+ _gcry_rndjent_dump_stats ();
+}
+
+
+/* This function should be called during initialization and before
+ initialization of this module to place the random pools into secure
+ memory. */
+void
+_gcry_secure_random_alloc (void)
+{
+ if (fips_mode ())
+ ; /* Not used; the FIPS RNG is always in secure mode. */
+ else
+ _gcry_rngcsprng_secure_alloc ();
+}
+
+
+/* This may be called before full initialization to degrade the
+ quality of the RNG for the sake of a faster running test suite. */
+void
+_gcry_enable_quick_random_gen (void)
+{
+ if (fips_mode ())
+ ; /* Not used. */
+ else
+ _gcry_rngcsprng_enable_quick_gen ();
+}
+
+
+void
+_gcry_set_random_daemon_socket (const char *socketname)
+{
+ if (fips_mode ())
+ ; /* Not used. */
+ else
+ _gcry_rngcsprng_set_daemon_socket (socketname);
+}
+
+/* With ONOFF set to 1, enable the use of the daemon. With ONOFF set
+ to 0, disable the use of the daemon. With ONOF set to -1, return
+ whether the daemon has been enabled. */
+int
+_gcry_use_random_daemon (int onoff)
+{
+ if (fips_mode ())
+ return 0; /* Never enabled in fips mode. */
+ else
+ return _gcry_rngcsprng_use_daemon (onoff);
+}
+
+
+/* This function returns true if no real RNG is available or the
+ quality of the RNG has been degraded for test purposes. */
+int
+_gcry_random_is_faked (void)
+{
+ if (fips_mode ())
+ return _gcry_rngdrbg_is_faked ();
+ else
+ return _gcry_rngcsprng_is_faked ();
+}
+
+
+/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
+ should be in the range of 0..100 to indicate the goodness of the
+ entropy added, or -1 for goodness not known. */
+gcry_err_code_t
+_gcry_random_add_bytes (const void *buf, size_t buflen, int quality)
+{
+ if (fips_mode ())
+ return 0; /* No need for this in fips mode. */
+ else if (rng_types.standard)
+ return gpg_err_code (_gcry_rngcsprng_add_bytes (buf, buflen, quality));
+ else if (rng_types.fips)
+ return 0;
+ else if (rng_types.system)
+ return 0;
+ else /* default */
+ return gpg_err_code (_gcry_rngcsprng_add_bytes (buf, buflen, quality));
+}
+
+
+/* Helper function. */
+static void
+do_randomize (void *buffer, size_t length, enum gcry_random_level level)
+{
+ if (fips_mode ())
+ _gcry_rngdrbg_randomize (buffer, length, level);
+ else if (rng_types.standard)
+ _gcry_rngcsprng_randomize (buffer, length, level);
+ else if (rng_types.fips)
+ _gcry_rngdrbg_randomize (buffer, length, level);
+ else if (rng_types.system)
+ _gcry_rngsystem_randomize (buffer, length, level);
+ else /* default */
+ _gcry_rngcsprng_randomize (buffer, length, level);
+}
+
+/* The public function to return random data of the quality LEVEL.
+ Returns a pointer to a newly allocated and randomized buffer of
+ LEVEL and NBYTES length. Caller must free the buffer. */
+void *
+_gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
+{
+ void *buffer;
+
+ buffer = xmalloc (nbytes);
+ do_randomize (buffer, nbytes, level);
+ return buffer;
+}
+
+
+/* The public function to return random data of the quality LEVEL;
+ this version of the function returns the random in a buffer allocated
+ in secure memory. Caller must free the buffer. */
+void *
+_gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
+{
+ void *buffer;
+
+ /* Historical note (1.3.0--1.4.1): The buffer was only allocated
+ in secure memory if the pool in random-csprng.c was also set to
+ use secure memory. */
+ buffer = xmalloc_secure (nbytes);
+ do_randomize (buffer, nbytes, level);
+ return buffer;
+}
+
+
+/* Public function to fill the buffer with LENGTH bytes of
+ cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
+ not very strong, GCRY_STRONG_RANDOM is strong enough for most
+ usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
+ may be very slow. */
+void
+_gcry_randomize (void *buffer, size_t length, enum gcry_random_level level)
+{
+ do_randomize (buffer, length, level);
+}
+
+
+/* This function may be used to specify the file to be used as a seed
+ file for the PRNG. This function should be called prior to the
+ initialization of the random module. NAME may not be NULL. */
+void
+_gcry_set_random_seed_file (const char *name)
+{
+ if (fips_mode ())
+ ; /* No need for this in fips mode. */
+ else if (rng_types.standard)
+ _gcry_rngcsprng_set_seed_file (name);
+ else if (rng_types.fips)
+ ;
+ else if (rng_types.system)
+ ;
+ else /* default */
+ _gcry_rngcsprng_set_seed_file (name);
+}
+
+
+/* If a seed file has been setup, this function may be used to write
+ back the random numbers entropy pool. */
+void
+_gcry_update_random_seed_file (void)
+{
+ if (fips_mode ())
+ ; /* No need for this in fips mode. */
+ else if (rng_types.standard)
+ _gcry_rngcsprng_update_seed_file ();
+ else if (rng_types.fips)
+ ;
+ else if (rng_types.system)
+ ;
+ else /* default */
+ _gcry_rngcsprng_update_seed_file ();
+}
+
+
+
+/* The fast random pool function as called at some places in
+ libgcrypt. This is merely a wrapper to make sure that this module
+ is initialized and to lock the pool. Note, that this function is a
+ NOP unless a random function has been used or _gcry_initialize (1)
+ has been used. We use this hack so that the internal use of this
+ function in cipher_open and md_open won't start filling up the
+ random pool, even if no random will be required by the process. */
+void
+_gcry_fast_random_poll (void)
+{
+ if (fips_mode ())
+ ; /* No need for this in fips mode. */
+ else if (rng_types.standard)
+ _gcry_rngcsprng_fast_poll ();
+ else if (rng_types.fips)
+ ;
+ else if (rng_types.system)
+ ;
+ else /* default */
+ _gcry_rngcsprng_fast_poll ();
+}
+
+
+
+/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
+void
+_gcry_create_nonce (void *buffer, size_t length)
+{
+ static unsigned char nonce_buffer[20+8];
+ static int nonce_buffer_initialized = 0;
+ static volatile pid_t my_pid; /* The volatile is there to make sure the
+ compiler does not optimize the code away
+ in case the getpid function is badly
+ attributed. */
+ volatile pid_t apid;
+ unsigned char *p;
+ size_t n;
+ int err;
+
+ /* First check whether we shall use the FIPS nonce generator. This
+ is only done in FIPS mode, in all other modes, we use our own
+ nonce generator which is seeded by the RNG actual in use. */
+ if (fips_mode ())
+ {
+ _gcry_rngdrbg_randomize (buffer, length, GCRY_WEAK_RANDOM);
+ return;
+ }
+
+ /* This is the nonce generator, which formerly lived in
+ random-csprng.c. It is now used by all RNG types except when in
+ FIPS mode (not that this means it is also used if the FIPS RNG
+ has been selected but we are not in fips mode). */
+
+ /* Make sure we are initialized. */
+ _gcry_random_initialize (1);
+
+ /* Acquire the nonce buffer lock. */
+ err = gpgrt_lock_lock (&nonce_buffer_lock);
+ if (err)
+ log_fatal ("failed to acquire the nonce buffer lock: %s\n",
+ gpg_strerror (err));
+
+ apid = getpid ();
+ /* The first time initialize our buffer. */
+ if (!nonce_buffer_initialized)
+ {
+ time_t atime = time (NULL);
+ pid_t xpid = apid;
+
+ my_pid = apid;
+
+ if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
+ BUG ();
+
+ /* Initialize the first 20 bytes with a reasonable value so that
+ a failure of gcry_randomize won't affect us too much. Don't
+ care about the uninitialized remaining bytes. */
+ p = nonce_buffer;
+ memcpy (p, &xpid, sizeof xpid);
+ p += sizeof xpid;
+ memcpy (p, &atime, sizeof atime);
+
+ /* Initialize the never changing private part of 64 bits. */
+ _gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
+
+ nonce_buffer_initialized = 1;
+ }
+ else if ( my_pid != apid )
+ {
+ /* We forked. Need to reseed the buffer - doing this for the
+ private part should be sufficient. */
+ do_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
+ /* Update the pid so that we won't run into here again and
+ again. */
+ my_pid = apid;
+ }
+
+ /* Create the nonce by hashing the entire buffer, returning the hash
+ and updating the first 20 bytes of the buffer with this hash. */
+ for (p = buffer; length > 0; length -= n, p += n)
+ {
+ _gcry_sha1_hash_buffer (nonce_buffer,
+ nonce_buffer, sizeof nonce_buffer);
+ n = length > 20? 20 : length;
+ memcpy (p, nonce_buffer, n);
+ }
+
+ /* Release the nonce buffer lock. */
+ err = gpgrt_lock_unlock (&nonce_buffer_lock);
+ if (err)
+ log_fatal ("failed to release the nonce buffer lock: %s\n",
+ gpg_strerror (err));
+}
+
+
+/* Run the self-tests for the RNG. This is currently only implemented
+ for the FIPS generator. */
+gpg_error_t
+_gcry_random_selftest (selftest_report_func_t report)
+{
+ if (fips_mode ())
+ return _gcry_rngdrbg_selftest (report);
+ else
+ return 0; /* No selftests yet. */
+}
diff --git a/comm/third_party/libgcrypt/random/random.h b/comm/third_party/libgcrypt/random/random.h
new file mode 100644
index 0000000000..c00b9ed537
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/random.h
@@ -0,0 +1,79 @@
+/* random.h - random functions
+ * Copyright (C) 1998, 2002, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef G10_RANDOM_H
+#define G10_RANDOM_H
+
+#include "types.h"
+#include "../src/gcrypt-testapi.h" /* struct gcry_drbg_test_vector */
+
+/*-- random.c --*/
+void _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
+ void *cb_data );
+
+void _gcry_set_preferred_rng_type (int type);
+void _gcry_random_initialize (int full);
+void _gcry_random_close_fds (void);
+int _gcry_get_rng_type (int ignore_fips_mode);
+void _gcry_random_dump_stats(void);
+void _gcry_secure_random_alloc(void);
+void _gcry_enable_quick_random_gen (void);
+int _gcry_random_is_faked(void);
+void _gcry_set_random_daemon_socket (const char *socketname);
+int _gcry_use_random_daemon (int onoff);
+void _gcry_set_random_seed_file (const char *name);
+void _gcry_update_random_seed_file (void);
+
+void _gcry_fast_random_poll( void );
+
+gcry_err_code_t _gcry_random_init_external_test (void **r_context,
+ unsigned int flags,
+ const void *key,
+ size_t keylen,
+ const void *seed,
+ size_t seedlen,
+ const void *dt,
+ size_t dtlen);
+gcry_err_code_t _gcry_random_run_external_test (void *context,
+ char *buffer, size_t buflen);
+void _gcry_random_deinit_external_test (void *context);
+
+/*-- random-drbg.c --*/
+gpg_err_code_t _gcry_rngdrbg_reinit (const char *flagstr,
+ gcry_buffer_t *pers, int npers);
+gpg_err_code_t _gcry_rngdrbg_cavs_test (struct gcry_drbg_test_vector *t,
+ unsigned char *buf);
+gpg_err_code_t _gcry_rngdrbg_healthcheck_one (struct gcry_drbg_test_vector *t);
+
+/*-- rndegd.c --*/
+gpg_error_t _gcry_rndegd_set_socket_name (const char *name);
+
+/*-- rndjent.c --*/
+unsigned int _gcry_rndjent_get_version (int *r_active);
+
+
+/*-- random-daemon.c (only used from random.c) --*/
+#ifdef USE_RANDOM_DAEMON
+void _gcry_daemon_initialize_basics (void);
+int _gcry_daemon_randomize (const char *socketname,
+ void *buffer, size_t length,
+ enum gcry_random_level level);
+#endif /*USE_RANDOM_DAEMON*/
+
+#endif /*G10_RANDOM_H*/
diff --git a/comm/third_party/libgcrypt/random/rndegd.c b/comm/third_party/libgcrypt/random/rndegd.c
new file mode 100644
index 0000000000..b87115f234
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndegd.c
@@ -0,0 +1,290 @@
+/* rndegd.c - interface to the EGD
+ * Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "types.h"
+#include "g10lib.h"
+#include "cipher.h"
+#include "rand-internal.h"
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t) &((type *)0)->member)
+#endif
+
+static int egd_socket = -1;
+
+/* Allocated name of the socket if supplied at runtime. */
+static char *user_socket_name;
+
+
+/* Allocate a new filename from FIRST_PART and SECOND_PART and to
+ tilde expansion for first_part. SECOND_PART might be NULL.
+ */
+static char *
+my_make_filename (const char *first_part, const char *second_part)
+{
+ size_t n;
+ char *name, *home, *p;
+
+ n = strlen(first_part)+1;
+ if (second_part)
+ n += strlen (second_part) + 1;
+
+ home = NULL;
+ if( *first_part == '~' && first_part[1] == '/'
+ && (home = getenv("HOME")) && *home )
+ n += strlen(home);
+
+ name = _gcry_xmalloc(n);
+ p = (home
+ ? stpcpy (stpcpy (name, home), first_part+1 )
+ : stpcpy (name, first_part) );
+
+ if (second_part)
+ strcpy (stpcpy(p,"/"), second_part);
+
+ return name;
+}
+
+
+static int
+do_write( int fd, void *buf, size_t nbytes )
+{
+ size_t nleft = nbytes;
+ int nwritten;
+
+ while( nleft > 0 )
+ {
+ nwritten = write( fd, buf, nleft);
+ if( nwritten < 0 )
+ {
+ if( errno == EINTR )
+ continue;
+ return -1;
+ }
+ nleft -= nwritten;
+ buf = (char*)buf + nwritten;
+ }
+ return 0;
+}
+
+static int
+do_read( int fd, void *buf, size_t nbytes )
+{
+ int n, nread = 0;
+
+ do
+ {
+ do
+ {
+ n = read(fd, (char*)buf + nread, nbytes );
+ }
+ while( n == -1 && errno == EINTR );
+ if( n == -1)
+ return nread? nread:-1;
+ if( n == 0)
+ return -1;
+ nread += n;
+ nbytes -= n;
+ }
+ while( nread < nbytes );
+ return nread;
+}
+
+
+/* Note that his function is not thread-safe. */
+gpg_error_t
+_gcry_rndegd_set_socket_name (const char *name)
+{
+ char *newname;
+ struct sockaddr_un addr;
+
+ newname = my_make_filename (name, NULL);
+ if (strlen (newname)+1 >= sizeof addr.sun_path)
+ {
+ xfree (newname);
+ return gpg_error_from_syserror ();
+ }
+ xfree (user_socket_name);
+ user_socket_name = newname;
+ return 0;
+}
+
+
+/* Connect to the EGD and return the file descriptor. Return -1 on
+ error. With NOFAIL set to true, silently fail and return the
+ error, otherwise print an error message and die. */
+int
+_gcry_rndegd_connect_socket (int nofail)
+{
+ int fd;
+ const char *bname = NULL;
+ char *name;
+ struct sockaddr_un addr;
+ int addr_len;
+
+ if (egd_socket != -1)
+ {
+ close (egd_socket);
+ egd_socket = -1;
+ }
+
+#ifdef EGD_SOCKET_NAME
+ bname = EGD_SOCKET_NAME;
+#endif
+ if (user_socket_name)
+ {
+ name = _gcry_strdup (user_socket_name);
+ if (!name)
+ {
+ if (!nofail)
+ log_fatal ("error allocating memory in rndegd: %s\n",
+ strerror(errno) );
+ return -1;
+ }
+ }
+ else if ( !bname || !*bname )
+ name = my_make_filename ("~/.gnupg", "entropy");
+ else
+ name = my_make_filename (bname, NULL);
+
+ if (strlen(name)+1 >= sizeof addr.sun_path)
+ log_fatal ("EGD socketname is too long\n");
+
+ memset( &addr, 0, sizeof addr );
+ addr.sun_family = AF_UNIX;
+ strcpy( addr.sun_path, name );
+ addr_len = (offsetof( struct sockaddr_un, sun_path )
+ + strlen( addr.sun_path ));
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1 && !nofail)
+ log_fatal("can't create unix domain socket: %s\n", strerror(errno) );
+ else if (connect (fd, (struct sockaddr*)&addr, addr_len) == -1)
+ {
+ if (!nofail)
+ log_fatal("can't connect to EGD socket `%s': %s\n",
+ name, strerror(errno) );
+ close (fd);
+ fd = -1;
+ }
+ xfree (name);
+ if (fd != -1)
+ egd_socket = fd;
+ return fd;
+}
+
+/****************
+ * Note: We always use the highest level.
+ * To boost the performance we may want to add some
+ * additional code for level 1
+ *
+ * Using a level of 0 should never block and better add nothing
+ * to the pool. So this is just a dummy for EGD.
+ */
+int
+_gcry_rndegd_gather_random (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level )
+{
+ int fd = egd_socket;
+ int n;
+ byte buffer[256+2];
+ int nbytes;
+ int do_restart = 0;
+
+ if( !length )
+ return 0;
+ if( !level )
+ return 0;
+
+ restart:
+ if (fd == -1 || do_restart)
+ fd = _gcry_rndegd_connect_socket (0);
+
+ do_restart = 0;
+
+ nbytes = length < 255? length : 255;
+ /* First time we do it with a non blocking request */
+ buffer[0] = 1; /* non blocking */
+ buffer[1] = nbytes;
+ if( do_write( fd, buffer, 2 ) == -1 )
+ log_fatal("can't write to the EGD: %s\n", strerror(errno) );
+ n = do_read( fd, buffer, 1 );
+ if( n == -1 )
+ {
+ log_error("read error on EGD: %s\n", strerror(errno));
+ do_restart = 1;
+ goto restart;
+ }
+ n = buffer[0];
+ if( n )
+ {
+ n = do_read( fd, buffer, n );
+ if( n == -1 )
+ {
+ log_error("read error on EGD: %s\n", strerror(errno));
+ do_restart = 1;
+ goto restart;
+ }
+ (*add)( buffer, n, origin );
+ length -= n;
+ }
+
+ if( length )
+ {
+ log_info (
+ _("Please wait, entropy is being gathered. Do some work if it would\n"
+ "keep you from getting bored, because it will improve the quality\n"
+ "of the entropy.\n") );
+ }
+ while( length )
+ {
+ nbytes = length < 255? length : 255;
+
+ buffer[0] = 2; /* blocking */
+ buffer[1] = nbytes;
+ if( do_write( fd, buffer, 2 ) == -1 )
+ log_fatal("can't write to the EGD: %s\n", strerror(errno) );
+ n = do_read( fd, buffer, nbytes );
+ if( n == -1 )
+ {
+ log_error("read error on EGD: %s\n", strerror(errno));
+ do_restart = 1;
+ goto restart;
+ }
+ (*add)( buffer, n, origin );
+ length -= n;
+ }
+ memset(buffer, 0, sizeof(buffer) );
+
+ return 0; /* success */
+}
diff --git a/comm/third_party/libgcrypt/random/rndhw.c b/comm/third_party/libgcrypt/random/rndhw.c
new file mode 100644
index 0000000000..3cf9acc3a2
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndhw.c
@@ -0,0 +1,230 @@
+/* rndhw.c - Access to the external random daemon
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2012 Dmitry Kasatkin
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+#undef USE_PADLOCK
+#ifdef ENABLE_PADLOCK_SUPPORT
+# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
+# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)
+# define USE_PADLOCK 1
+# endif
+# endif
+#endif /*ENABLE_PADLOCK_SUPPORT*/
+
+#undef USE_DRNG
+#ifdef ENABLE_DRNG_SUPPORT
+# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
+# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)
+# define USE_DRNG 1
+# endif
+# endif
+#endif /*ENABLE_RDRAND_SUPPORT*/
+
+typedef void (*add_fn_t)(const void*, size_t, enum random_origins);
+
+/* Keep track on whether the RNG has problems. */
+static volatile int rng_failed;
+
+
+#ifdef USE_PADLOCK
+static size_t
+poll_padlock (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins origin, int fast)
+{
+ volatile char buffer[64+8] __attribute__ ((aligned (8)));
+ volatile char *p;
+ unsigned int nbytes, status;
+
+ /* Peter Gutmann's cryptlib tests again whether the RNG is enabled
+ but we don't do so. We would have to do this also for our AES
+ implementation and that is definitely too time consuming. There
+ would be a race condition anyway. Thus we assume that the OS
+ does not change the Padlock initialization while a user process
+ is running. */
+ p = buffer;
+ nbytes = 0;
+ while (nbytes < 64)
+ {
+#if defined(__x86_64__) && SIZEOF_VOID_P == 8
+ asm volatile
+ ("movq %1, %%rdi\n\t" /* Set buffer. */
+ "xorq %%rdx, %%rdx\n\t" /* Request up to 8 bytes. */
+ ".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */
+ : "=a" (status)
+ : "g" (p)
+ : "%rdx", "%rdi", "cc", "memory"
+ );
+#else
+ asm volatile
+ ("movl %1, %%edi\n\t" /* Set buffer. */
+ "xorl %%edx, %%edx\n\t" /* Request up to 8 bytes. */
+ ".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */
+ : "=a" (status)
+ : "g" (p)
+ : "%edx", "%edi", "cc", "memory"
+ );
+#endif
+ if ((status & (1<<6)) /* RNG still enabled. */
+ && !(status & (1<<13)) /* von Neumann corrector is enabled. */
+ && !(status & (1<<14)) /* String filter is disabled. */
+ && !(status & 0x1c00) /* BIAS voltage at default. */
+ && (!(status & 0x1f) || (status & 0x1f) == 8) /* Sanity check. */
+ )
+ {
+ nbytes += (status & 0x1f);
+ if (fast)
+ break; /* Don't get into the loop with the fast flag set. */
+ p += (status & 0x1f);
+ }
+ else
+ {
+ /* If there was an error we need to break the loop and
+ record that there is something wrong with the padlock
+ RNG. */
+ rng_failed = 1;
+ break;
+ }
+ }
+
+ if (nbytes)
+ {
+ (*add) ((void*)buffer, nbytes, origin);
+ wipememory (buffer, nbytes);
+ }
+ return nbytes;
+}
+#endif /*USE_PADLOCK*/
+
+
+#ifdef USE_DRNG
+# define RDRAND_RETRY_LOOPS 10
+# define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
+# if defined(__x86_64__) && SIZEOF_UNSIGNED_LONG == 8
+# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
+# else
+# define RDRAND_LONG RDRAND_INT
+# endif
+static inline int
+rdrand_long (volatile unsigned long *v)
+{
+ int ok;
+ asm volatile ("1: " RDRAND_LONG "\n\t"
+ "jc 2f\n\t"
+ "decl %0\n\t"
+ "jnz 1b\n\t"
+ "2:"
+ : "=r" (ok), "=a" (*v)
+ : "0" (RDRAND_RETRY_LOOPS)
+ : "cc", "memory");
+ return ok;
+}
+
+
+static inline int
+rdrand_nlong (volatile unsigned long *v, int count)
+{
+ while (count--)
+ if (!rdrand_long(v++))
+ return 0;
+ return 1;
+}
+
+
+static size_t
+poll_drng (add_fn_t add, enum random_origins origin, int fast)
+{
+ volatile unsigned long buffer[8] __attribute__ ((aligned (8)));
+ unsigned int nbytes = sizeof (buffer);
+
+ (void)fast;
+
+ if (!rdrand_nlong (buffer, DIM(buffer)))
+ return 0;
+ (*add)((void *)buffer, nbytes, origin);
+ return nbytes;
+}
+#endif /*USE_DRNG*/
+
+
+int
+_gcry_rndhw_failed_p (void)
+{
+ return rng_failed;
+}
+
+
+/* Try to read random from a hardware RNG if a fast one is
+ available. */
+void
+_gcry_rndhw_poll_fast (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins origin)
+{
+ (void)add;
+ (void)origin;
+
+#ifdef USE_DRNG
+ if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
+ poll_drng (add, origin, 1);
+#endif
+#ifdef USE_PADLOCK
+ if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG))
+ poll_padlock (add, origin, 1);
+#endif
+}
+
+
+/* Read 64 bytes from a hardware RNG and return the number of bytes
+ actually read. However hardware source is let account only
+ for up to 50% (or 25% for RDRAND) of the requested bytes. */
+size_t
+_gcry_rndhw_poll_slow (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins origin, size_t req_length)
+{
+ size_t nbytes = 0;
+
+ (void)add;
+ (void)origin;
+
+ req_length /= 2; /* Up to 50%. */
+
+#ifdef USE_DRNG
+ if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
+ {
+ req_length /= 2; /* Up to 25%. */
+ nbytes += poll_drng (add, origin, 0);
+ }
+#endif
+#ifdef USE_PADLOCK
+ if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG))
+ nbytes += poll_padlock (add, origin, 0);
+#endif
+
+ if (nbytes > req_length)
+ nbytes = req_length;
+
+ return nbytes;
+}
diff --git a/comm/third_party/libgcrypt/random/rndjent.c b/comm/third_party/libgcrypt/random/rndjent.c
new file mode 100644
index 0000000000..56648a8756
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndjent.c
@@ -0,0 +1,389 @@
+/* rndjent.c - Driver for the jitterentropy module.
+ * Copyright (C) 2017 g10 Code GmbH
+ * Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
+ * Copyright (C) 2013 Stephan Mueller <smueller@chronox.de>
+ *
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "types.h"
+#include "g10lib.h"
+#include "../cipher/bithelp.h"
+#include "rand-internal.h"
+
+/*
+ * Decide whether we can support jent at compile time.
+ */
+#undef USE_JENT
+#define JENT_USES_RDTSC 1
+#define JENT_USES_GETTIME 2
+#define JENT_USES_READ_REAL_TIME 3
+#ifdef ENABLE_JENT_SUPPORT
+# if (defined (__i386__) || defined(__x86_64__)) && defined(HAVE_CPU_ARCH_X86)
+# define USE_JENT JENT_USES_RDTSC
+# elif defined (HAVE_CLOCK_GETTIME)
+# if _AIX
+# define USE_JENT JENT_USES_READ_REAL_TIME
+# else
+# define USE_JENT JENT_USES_GETTIME
+# endif
+# endif
+#endif /*ENABLE_JENT_SUPPORT*/
+
+
+#ifdef USE_JENT
+
+#undef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+/* Uncomment the next line to build with statistics. */
+/* #define CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT 1 */
+
+
+/* Note that we source include the actual jitter entropy code.
+ * Platform dependent code is indirectly included from our own
+ * jitterentropy-user-base.h file. */
+
+/* Tell jitterentropy* that all functions shall be static. */
+#define JENT_PRIVATE_COMPILE 1
+
+#include "jitterentropy-base.c"
+
+
+/* This is the lock we use to serialize access to this RNG. The extra
+ * integer variable is only used to check the locking state; that is,
+ * it is not meant to be thread-safe but merely as a failsafe feature
+ * to assert proper locking. */
+GPGRT_LOCK_DEFINE (jent_rng_lock);
+static int jent_rng_is_locked;
+
+/* This flag tracks whether the RNG has been initialized - either
+ * with error or with success. Protected by JENT_RNG_LOCK. */
+static int jent_rng_is_initialized;
+
+/* Our collector. The RNG is in a working state if its value is not
+ * NULL. Protected by JENT_RNG_LOCK. */
+struct rand_data *jent_rng_collector;
+
+/* The number of times the core entropy function has been called and
+ * the number of random bytes retrieved. */
+static unsigned long jent_rng_totalcalls;
+static unsigned long jent_rng_totalbytes;
+
+
+
+/* JENT statistic helper code. */
+#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
+
+static void
+jent_init_statistic (struct rand_data *rand_data)
+{
+ /* int i; */
+ /* struct entropy_stat *stat = &rand_data->entropy_stat; */
+
+ /* for (i = 0; i < 64; i++) */
+ /* { */
+ /* stat->bitslot[i] = 0; */
+ /* stat->bitvar[i] = 0; */
+ /* } */
+
+ /* jent_get_nstime (&stat->collection_begin); */
+}
+
+static void
+jent_bit_count (struct rand_data *rand_data, u64 prev_data)
+{
+ /* int i; */
+
+ /* if (!rand_data->entropy_stat.enable_bit_test) */
+ /* return; */
+
+ /* for (i = 0; i < 64; i++) */
+ /* { */
+ /* /\* collect the count of set bits per bit position in the */
+ /* * current ->data field *\/ */
+ /* rand_data->entropy_stat.bitslot[i] += (rand_data->data & 1<<i) ? 1:0; */
+
+ /* /\* collect the count of bit changes between the current */
+ /* * and the previous random data value per bit position *\/ */
+ /* if ((rand_data->data & 1<<i) != (prev_data & 1<<i)) */
+ /* rand_data->entropy_stat.bitvar[i] += 1; */
+ /* } */
+}
+
+
+static void
+jent_statistic_copy_stat (struct entropy_stat *src, struct entropy_stat *dst)
+{
+ /* /\* not copying bitslot and bitvar as they are not needed for */
+ /* * statistic printout *\/ */
+ /* dst->collection_begin = src->collection_begin; */
+ /* dst->collection_end = src->collection_end; */
+ /* dst->old_delta = src->old_delta; */
+ /* dst->setbits = src->setbits; */
+ /* dst->varbits = src->varbits; */
+ /* dst->obsbits = src->obsbits; */
+ /* dst->collection_loop_cnt= src->collection_loop_cnt; */
+}
+
+
+/*
+ * Assessment of statistical behavior of the generated output and returning
+ * the information to the caller by filling the target value.
+ *
+ * Details about the bit statistics are given in chapter 4 of the doc.
+ * Chapter 5 documents the timer analysis and the resulting entropy.
+ */
+static void
+jent_calc_statistic (struct rand_data *rand_data,
+ struct entropy_stat *target, unsigned int loop_cnt)
+{
+ /* int i; */
+ /* struct entropy_stat *stat = &rand_data->entropy_stat; */
+
+ /* jent_get_nstime(&stat->collection_end); */
+
+ /* stat->collection_loop_cnt = loop_cnt; */
+
+ /* stat->setbits = 0; */
+ /* stat->varbits = 0; */
+ /* stat->obsbits = 0; */
+
+ /* for (i = 0; i < DATA_SIZE_BITS; i++) */
+ /* { */
+ /* stat->setbits += stat->bitslot[i]; */
+ /* stat->varbits += stat->bitvar[i]; */
+
+ /* /\* This is the sum of set bits in the current observation */
+ /* * of the random data. *\/ */
+ /* stat->obsbits += (rand_data->data & 1<<i) ? 1:0; */
+ /* } */
+
+ /* jent_statistic_copy_stat(stat, target); */
+
+ /* stat->old_delta = (stat->collection_end - stat->collection_begin); */
+}
+
+#endif /*CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT*/
+
+
+/* Acquire the jent_rng_lock. */
+static void
+lock_rng (void)
+{
+ gpg_err_code_t rc;
+
+ rc = gpgrt_lock_lock (&jent_rng_lock);
+ if (rc)
+ log_fatal ("failed to acquire the Jent RNG lock: %s\n",
+ gpg_strerror (rc));
+ jent_rng_is_locked = 1;
+}
+
+
+/* Release the jent_rng_lock. */
+static void
+unlock_rng (void)
+{
+ gpg_err_code_t rc;
+
+ jent_rng_is_locked = 0;
+ rc = gpgrt_lock_unlock (&jent_rng_lock);
+ if (rc)
+ log_fatal ("failed to release the Jent RNG lock: %s\n",
+ gpg_strerror (rc));
+}
+
+
+/* Return true if the JENT RNG code can be run. It may not yet been
+ * initialized, though. */
+static int
+is_rng_available (void)
+{
+#if USE_JENT == JENT_USES_RDTSC
+ return !!(_gcry_get_hw_features () & HWF_INTEL_RDTSC);
+#elif USE_JENT == JENT_USES_GETTIME
+ return 2;
+#elif USE_JENT == JENT_USES_READ_REAL_TIME
+ return 3;
+#else /* Ooops */
+ return 0;
+#endif
+}
+
+#endif /* USE_JENT */
+
+
+/*
+ * The API used by the high level code.
+ */
+
+/* Read up to LENGTH bytes from a jitter RNG and return the number of
+ * bytes actually read. */
+size_t
+_gcry_rndjent_poll (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins origin, size_t length)
+{
+ size_t nbytes = 0;
+
+#ifdef USE_JENT
+ if ( is_rng_available () )
+ {
+ lock_rng ();
+
+ if (!jent_rng_is_initialized)
+ {
+ /* Auto-initialize. */
+ jent_rng_is_initialized = 1;
+ jent_entropy_collector_free (jent_rng_collector);
+ jent_rng_collector = NULL;
+ if ( !(_gcry_random_read_conf () & RANDOM_CONF_DISABLE_JENT))
+ {
+ if (!jent_entropy_init ())
+ jent_rng_collector = jent_entropy_collector_alloc (1, 0);
+ }
+ }
+
+ if (jent_rng_collector && add)
+ {
+ /* We have a working JENT and it has not been disabled. */
+ char buffer[32];
+
+ while (length)
+ {
+ int rc;
+ size_t n = length < sizeof(buffer)? length : sizeof (buffer);
+
+ jent_rng_totalcalls++;
+ rc = jent_read_entropy (jent_rng_collector, buffer, n);
+ if (rc < 0)
+ break;
+ /* We need to hash the output to conform to the BSI
+ * NTG.1 specs. */
+ _gcry_md_hash_buffer (GCRY_MD_SHA256, buffer, buffer, rc);
+ n = rc < 32? rc : 32;
+ (*add) (buffer, n, origin);
+ length -= n;
+ nbytes += n;
+ jent_rng_totalbytes += n;
+ }
+ wipememory (buffer, sizeof buffer);
+ }
+
+ unlock_rng ();
+ }
+
+#else
+
+ (void)add;
+ (void)origin;
+
+#endif
+
+ return nbytes;
+}
+
+
+/* Return the version number of the JENT RNG. If the RNG is not
+ * initialized or usable 0 is returned. If R_ACTIVE is not NULL the
+ * jitter RNG will be initialized and true is stored at R_ACTIVE if
+ * the initialization succeeded. */
+unsigned int
+_gcry_rndjent_get_version (int *r_active)
+{
+ if (r_active)
+ *r_active = 0;
+#ifdef USE_JENT
+ if ( is_rng_available () )
+ {
+ if (r_active)
+ {
+ /* Make sure the RNG is initialized. */
+ _gcry_rndjent_poll (NULL, 0, 0);
+
+ lock_rng ();
+ /* To ease debugging we store 2 for a clock_gettime based
+ * implementation and 1 for a rdtsc based code. */
+ *r_active = jent_rng_collector? is_rng_available () : 0;
+ unlock_rng ();
+ }
+ return jent_version ();
+ }
+ else
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+/* Log statistical informantion about the use of this module. */
+void
+_gcry_rndjent_dump_stats (void)
+{
+ /* In theory we would need to lock the stats here. However this
+ * function is usually called during cleanup and then we _might_ run
+ * into problems. */
+
+#ifdef USE_JENT
+ if ( is_rng_available () )
+ {
+ log_info ("rndjent stat: collector=%p calls=%lu bytes=%lu\n",
+ jent_rng_collector, jent_rng_totalcalls, jent_rng_totalbytes);
+
+ }
+#endif /*USE_JENT*/
+}
+
+
+void
+_gcry_rndjent_fini (void)
+{
+#ifdef USE_JENT
+ lock_rng ();
+
+ if (jent_rng_is_initialized)
+ {
+ jent_entropy_collector_free (jent_rng_collector);
+ jent_rng_collector = NULL;
+ }
+
+ unlock_rng ();
+#endif
+}
diff --git a/comm/third_party/libgcrypt/random/rndlinux.c b/comm/third_party/libgcrypt/random/rndlinux.c
new file mode 100644
index 0000000000..a7a78906d2
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndlinux.c
@@ -0,0 +1,366 @@
+/* rndlinux.c - raw random number for OSes with /dev/random
+ * Copyright (C) 1998, 2001, 2002, 2003, 2007,
+ * 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_GETTIMEOFDAY
+# include <sys/times.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#if defined(__APPLE__) && defined(__MACH__)
+#include <Availability.h>
+#ifdef __MAC_10_11
+extern int getentropy (void *buf, size_t buflen) __attribute__ ((weak_import));
+#define HAVE_GETENTROPY
+#endif
+#endif
+#if defined(__linux__) || !defined(HAVE_GETENTROPY)
+#ifdef HAVE_SYSCALL
+# include <sys/syscall.h>
+# ifdef __NR_getrandom
+# define getentropy(buf,buflen) syscall (__NR_getrandom, buf, buflen, 0)
+# endif
+#endif
+#endif
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+static int open_device (const char *name, int retry);
+
+
+static int
+set_cloexec_flag (int fd)
+{
+ int oldflags;
+
+ oldflags= fcntl (fd, F_GETFD, 0);
+ if (oldflags < 0)
+ return oldflags;
+ oldflags |= FD_CLOEXEC;
+ return fcntl (fd, F_SETFD, oldflags);
+}
+
+
+
+/*
+ * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it
+ * exists)). If RETRY is true, the function does not terminate with
+ * a fatal error but retries until it is able to reopen the device.
+ */
+static int
+open_device (const char *name, int retry)
+{
+ int fd;
+
+ if (retry)
+ _gcry_random_progress ("open_dev_random", 'X', 1, 0);
+ again:
+ fd = open (name, O_RDONLY);
+ if (fd == -1 && retry)
+ {
+ struct timeval tv;
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ _gcry_random_progress ("wait_dev_random", 'X', 0, (int)tv.tv_sec);
+ select (0, NULL, NULL, NULL, &tv);
+ goto again;
+ }
+ if (fd == -1)
+ log_fatal ("can't open %s: %s\n", name, strerror(errno) );
+
+ if (set_cloexec_flag (fd))
+ log_error ("error setting FD_CLOEXEC on fd %d: %s\n",
+ fd, strerror (errno));
+
+ /* We used to do the following check, however it turned out that this
+ is not portable since more OSes provide a random device which is
+ sometimes implemented as another device type.
+
+ struct stat sb;
+
+ if( fstat( fd, &sb ) )
+ log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
+ if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
+ log_fatal("invalid random device!\n" );
+ */
+ return fd;
+}
+
+
+/* Note that the caller needs to make sure that this function is only
+ * called by one thread at a time. The function returns 0 on success
+ * or true on failure (in which case the caller will signal a fatal
+ * error). This function should be entered only by one thread at a
+ * time. */
+int
+_gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level )
+{
+ static int fd_urandom = -1;
+ static int fd_random = -1;
+ static int only_urandom = -1;
+ static unsigned char ever_opened;
+ static volatile pid_t my_pid; /* The volatile is there to make sure
+ * the compiler does not optimize the
+ * code away in case the getpid
+ * function is badly attributed. */
+ volatile pid_t apid;
+ int fd;
+ int n;
+ byte buffer[768];
+ size_t n_hw;
+ size_t want = length;
+ size_t last_so_far = 0;
+ int any_need_entropy = 0;
+ int delay;
+
+ /* On the first call read the conf file to check whether we want to
+ * use only urandom. */
+ if (only_urandom == -1)
+ {
+ my_pid = getpid ();
+ if ((_gcry_random_read_conf () & RANDOM_CONF_ONLY_URANDOM))
+ only_urandom = 1;
+ else
+ only_urandom = 0;
+ }
+
+ if (!add)
+ {
+ /* Special mode to close the descriptors. */
+ if (fd_random != -1)
+ {
+ close (fd_random);
+ fd_random = -1;
+ }
+ if (fd_urandom != -1)
+ {
+ close (fd_urandom);
+ fd_urandom = -1;
+ }
+
+ _gcry_rndjent_fini ();
+ return 0;
+ }
+
+ /* Detect a fork and close the devices so that we don't use the old
+ * file descriptors. Note that open_device will be called in retry
+ * mode if the devices was opened by the parent process. */
+ apid = getpid ();
+ if (my_pid != apid)
+ {
+ if (fd_random != -1)
+ {
+ close (fd_random);
+ fd_random = -1;
+ }
+ if (fd_urandom != -1)
+ {
+ close (fd_urandom);
+ fd_urandom = -1;
+ }
+ my_pid = apid;
+ }
+
+
+ /* First read from a hardware source. Note that _gcry_rndhw_poll_slow lets
+ it account only for up to 50% (or 25% for RDRAND) of the requested
+ bytes. */
+ n_hw = _gcry_rndhw_poll_slow (add, origin, length);
+ if (length > 1)
+ length -= n_hw;
+
+ /* When using a blocking random generator try to get some entropy
+ * from the jitter based RNG. In this case we take up to 50% of the
+ * remaining requested bytes. */
+ if (level >= GCRY_VERY_STRONG_RANDOM)
+ {
+ n_hw = _gcry_rndjent_poll (add, origin, length/2);
+ if (n_hw > length/2)
+ n_hw = length/2;
+ if (length > 1)
+ length -= n_hw;
+ }
+
+
+ /* Open the requested device. The first time a device is to be
+ opened we fail with a fatal error if the device does not exists.
+ In case the device has ever been closed, further open requests
+ will however retry indefinitely. The rationale for this behaviour is
+ that we always require the device to be existent but want a more
+ graceful behaviour if the rarely needed close operation has been
+ used and the device needs to be re-opened later. */
+ if (level >= GCRY_VERY_STRONG_RANDOM && !only_urandom)
+ {
+ if (fd_random == -1)
+ {
+ fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1));
+ ever_opened |= 1;
+ }
+ fd = fd_random;
+ }
+ else
+ {
+ if (fd_urandom == -1)
+ {
+ fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2));
+ ever_opened |= 2;
+ }
+ fd = fd_urandom;
+ }
+
+ /* Enter the read loop. */
+ delay = 0; /* Start with 0 seconds so that we do no block on the
+ first iteration and in turn call the progress function
+ before blocking. To give the OS a better chance to
+ return with something we will actually use 100ms. */
+ while (length)
+ {
+ fd_set rfds;
+ struct timeval tv;
+ int rc;
+
+ /* If we have a modern operating system, we first try to use the new
+ * getentropy function. That call guarantees that the kernel's
+ * RNG has been properly seeded before returning any data. This
+ * is different from /dev/urandom which may, due to its
+ * non-blocking semantics, return data even if the kernel has
+ * not been properly seeded. And it differs from /dev/random by never
+ * blocking once the kernel is seeded. */
+#if defined(HAVE_GETENTROPY) || defined(__NR_getrandom)
+#if defined(__APPLE__) && defined(__MACH__)
+ if (&getentropy != NULL)
+#endif
+ {
+ long ret;
+ size_t nbytes;
+
+ do
+ {
+ nbytes = length < sizeof(buffer)? length : sizeof(buffer);
+ if (nbytes > 256)
+ nbytes = 256;
+ _gcry_pre_syscall ();
+ ret = getentropy (buffer, nbytes);
+ _gcry_post_syscall ();
+ }
+ while (ret == -1 && errno == EINTR);
+ if (ret == -1 && errno == ENOSYS)
+ ; /* getentropy is not supported - fallback to pulling from fd. */
+ else
+ { /* getentropy is supported. Some sanity checks. */
+ if (ret == -1)
+ log_fatal ("unexpected error from getentropy: %s\n",
+ strerror (errno));
+#ifdef __NR_getrandom
+ else if (ret != nbytes)
+ log_fatal ("getentropy returned only"
+ " %ld of %zu requested bytes\n", ret, nbytes);
+#endif
+
+ (*add)(buffer, nbytes, origin);
+ length -= nbytes;
+ continue; /* until LENGTH is zero. */
+ }
+ }
+#endif
+
+ /* If we collected some bytes update the progress indicator. We
+ do this always and not just if the select timed out because
+ often just a few bytes are gathered within the timeout
+ period. */
+ if (any_need_entropy || last_so_far != (want - length) )
+ {
+ last_so_far = want - length;
+ _gcry_random_progress ("need_entropy", 'X',
+ (int)last_so_far, (int)want);
+ any_need_entropy = 1;
+ }
+
+ /* If the system has no limit on the number of file descriptors
+ and we encounter an fd which is larger than the fd_set size,
+ we don't use the select at all. The select code is only used
+ to emit progress messages. A better solution would be to
+ fall back to poll() if available. */
+#ifdef FD_SETSIZE
+ if (fd < FD_SETSIZE)
+#endif
+ {
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tv.tv_sec = delay;
+ tv.tv_usec = delay? 0 : 100000;
+ _gcry_pre_syscall ();
+ rc = select (fd+1, &rfds, NULL, NULL, &tv);
+ _gcry_post_syscall ();
+ if (!rc)
+ {
+ any_need_entropy = 1;
+ delay = 3; /* Use 3 seconds henceforth. */
+ continue;
+ }
+ else if( rc == -1 )
+ {
+ log_error ("select() error: %s\n", strerror(errno));
+ if (!delay)
+ delay = 1; /* Use 1 second if we encounter an error before
+ we have ever blocked. */
+ continue;
+ }
+ }
+
+ do
+ {
+ size_t nbytes;
+
+ nbytes = length < sizeof(buffer)? length : sizeof(buffer);
+ n = read (fd, buffer, nbytes);
+ if (n >= 0 && n > nbytes)
+ {
+ log_error("bogus read from random device (n=%d)\n", n );
+ n = nbytes;
+ }
+ }
+ while (n == -1 && errno == EINTR);
+ if (n == -1)
+ log_fatal("read error on random device: %s\n", strerror(errno));
+ (*add)(buffer, n, origin);
+ length -= n;
+ }
+ wipememory (buffer, sizeof buffer);
+
+ if (any_need_entropy)
+ _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want);
+
+ return 0; /* success */
+}
diff --git a/comm/third_party/libgcrypt/random/rndunix.c b/comm/third_party/libgcrypt/random/rndunix.c
new file mode 100644
index 0000000000..aff2f85df5
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndunix.c
@@ -0,0 +1,937 @@
+/****************************************************************************
+ * *
+ * *
+ * Unix Randomness-Gathering Code *
+ * *
+ * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. *
+ * Heavily modified for GnuPG by Werner Koch *
+ * *
+ * *
+ ****************************************************************************/
+
+/* This module is part of the cryptlib continuously seeded pseudorandom
+ number generator. For usage conditions, see lib_rand.c
+
+ [Here is the notice from lib_rand.c:]
+
+ This module and the misc/rnd*.c modules represent the cryptlib
+ continuously seeded pseudorandom number generator (CSPRNG) as described in
+ my 1998 Usenix Security Symposium paper "The generation of random numbers
+ for cryptographic purposes".
+
+ The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
+ 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
+ modules 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
+ and this permission notice in its entirety.
+
+ 2. Redistributions in binary form must reproduce the copyright notice in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. A copy of any bugfixes or enhancements made must be provided to the
+ author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
+ baseline version of the code.
+
+ ALTERNATIVELY, the code may be distributed under the terms of the
+ GNU Lesser General Public License, version 2.1 or any later version
+ published by the Free Software Foundation, in which case the
+ provisions of the GNU LGPL are required INSTEAD OF the above
+ restrictions.
+
+ Although not required under the terms of the LGPL, it would still be
+ nice if you could make any changes available to the author to allow
+ a consistent code base to be maintained. */
+/*************************************************************************
+ The above alternative was changed from GPL to LGPL on 2007-08-22 with
+ permission from Peter Gutmann:
+ ==========
+ From: pgut001 <pgut001@cs.auckland.ac.nz>
+ Subject: Re: LGPL for the windows entropy gatherer
+ To: wk@gnupg.org
+ Date: Wed, 22 Aug 2007 03:05:42 +1200
+
+ Hi,
+
+ >As of now libgcrypt is GPL under Windows due to that module and some people
+ >would really like to see it under LGPL too. Can you do such a license change
+ >to LGPL version 2? Note that LGPL give the user the option to relicense it
+ >under GPL, so the change would be pretty easy and backwar compatible.
+
+ Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy
+ code as well, but Ian asked for LGPL as an option so as of the next release
+ I'll have LGPL in there. You can consider it to be retroactive, so your
+ current version will be LGPLd as well.
+
+ Peter.
+ ==========
+ From: pgut001 <pgut001@cs.auckland.ac.nz>
+ Subject: Re: LGPL for the windows entropy gatherer
+ To: wk@gnupg.org
+ Date: Wed, 22 Aug 2007 20:50:08 +1200
+
+ >Would you mind to extend this also to the Unix entropy gatherer which is
+ >still used on systems without /dev/random and when EGD is not installed? That
+ >would be the last GPLed piece in Libgcrypt.
+
+ Sure, it covers the entire entropy-gathering subsystem.
+
+ Peter.
+ =========
+*/
+
+/* General includes */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <string.h>
+
+/* OS-specific includes */
+
+#ifdef __osf__
+ /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in
+ * via the following includes are various endianness defines, so we
+ * undefine the cryptlib ones, which aren't really needed for this module
+ * anyway */
+#undef BIG_ENDIAN
+#undef LITTLE_ENDIAN
+#endif /* __osf__ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+#ifndef __QNX__
+#include <sys/errno.h>
+#include <sys/ipc.h>
+#endif /* __QNX__ */
+#include <sys/time.h> /* SCO and SunOS need this before resource.h */
+#ifndef __QNX__
+#include <sys/resource.h>
+#endif /* __QNX__ */
+#if defined( _AIX ) || defined( __QNX__ )
+#include <sys/select.h>
+#endif /* _AIX */
+#ifndef __QNX__
+#include <sys/shm.h>
+#include <signal.h>
+#include <sys/signal.h>
+#endif /* __QNX__ */
+#include <sys/stat.h>
+#include <sys/types.h> /* Verschiedene komische Typen */
+#if defined( __hpux ) && ( OS_VERSION == 9 )
+#include <vfork.h>
+#endif /* __hpux 9.x, after that it's in unistd.h */
+#include <sys/wait.h>
+/* #include <kitchensink.h> */
+#ifdef __QNX__
+#include <signal.h>
+#include <process.h>
+#endif /* __QNX__ */
+#include <errno.h>
+
+#include "types.h" /* for byte and u32 typedefs */
+#include "g10lib.h"
+#include "rand-internal.h"
+
+#ifndef EAGAIN
+#define EAGAIN EWOULDBLOCK
+#endif
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */
+
+/* The structure containing information on random-data sources. Each
+ * record contains the source and a relative estimate of its usefulness
+ * (weighting) which is used to scale the number of kB of output from the
+ * source (total = data_bytes / usefulness). Usually the weighting is in the
+ * range 1-3 (or 0 for especially useless sources), resulting in a usefulness
+ * rating of 1...3 for each kB of source output (or 0 for the useless
+ * sources).
+ *
+ * If the source is constantly changing (certain types of network statistics
+ * have this characteristic) but the amount of output is small, the weighting
+ * is given as a negative value to indicate that the output should be treated
+ * as if a minimum of 1K of output had been obtained. If the source produces
+ * a lot of output then the scale factor is fractional, resulting in a
+ * usefulness rating of < 1 for each kB of source output.
+ *
+ * In order to provide enough randomness to satisfy the requirements for a
+ * slow poll, we need to accumulate at least 20 points of usefulness (a
+ * typical system should get about 30 points).
+ *
+ * Some potential options are missed out because of special considerations.
+ * pstat -i and pstat -f can produce amazing amounts of output (the record
+ * is 600K on an Oracle server) which floods the buffer and doesn't yield
+ * anything useful (apart from perhaps increasing the entropy of the vmstat
+ * output a bit), so we don't bother with this. pstat in general produces
+ * quite a bit of output, but it doesn't change much over time, so it gets
+ * very low weightings. netstat -s produces constantly-changing output but
+ * also produces quite a bit of it, so it only gets a weighting of 2 rather
+ * than 3. The same holds for netstat -in, which gets 1 rather than 2.
+ *
+ * Some binaries are stored in different locations on different systems so
+ * alternative paths are given for them. The code sorts out which one to
+ * run by itself, once it finds an exectable somewhere it moves on to the
+ * next source. The sources are arranged roughly in their order of
+ * usefulness, occasionally sources which provide a tiny amount of
+ * relatively useless data are placed ahead of ones which provide a large
+ * amount of possibly useful data because another 100 bytes can't hurt, and
+ * it means the buffer won't be swamped by one or two high-output sources.
+ * All the high-output sources are clustered towards the end of the list
+ * for this reason. Some binaries are checked for in a certain order, for
+ * example under Slowaris /usr/ucb/ps understands aux as an arg, but the
+ * others don't. Some systems have conditional defines enabling alternatives
+ * to commands which don't understand the usual options but will provide
+ * enough output (in the form of error messages) to look like they're the
+ * real thing, causing alternative options to be skipped (we can't check the
+ * return either because some commands return peculiar, non-zero status even
+ * when they're working correctly).
+ *
+ * In order to maximise use of the buffer, the code performs a form of run-
+ * length compression on its input where a repeated sequence of bytes is
+ * replaced by the occurrence count mod 256. Some commands output an awful
+ * lot of whitespace, this measure greatly increases the amount of data we
+ * can fit in the buffer.
+ *
+ * When we scale the weighting using the SC() macro, some preprocessors may
+ * give a division by zero warning for the most obvious expression
+ * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
+ * trap), so we define a value SC_0 which evaluates to zero when fed to
+ * '1024 / SC_0' */
+
+#define SC( weight ) ( 1024 / weight ) /* Scale factor */
+#define SC_0 16384 /* SC( SC_0 ) evaluates to 0 */
+
+static struct RI {
+ const char *path; /* Path to check for existence of source */
+ const char *arg; /* Args for source */
+ const int usefulness; /* Usefulness of source */
+ FILE *pipe; /* Pipe to source as FILE * */
+ int pipeFD; /* Pipe to source as FD */
+ pid_t pid; /* pid of child for waitpid() */
+ int length; /* Quantity of output produced */
+ const int hasAlternative; /* Whether source has alt.location */
+} dataSources[] = {
+
+ { "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
+ { "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
+ { "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
+ { "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
+ { "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
+ { "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
+ { "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
+ { "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
+ { "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
+ { "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
+ { "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
+ { "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
+ { "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
+ { "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
+ { "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
+ SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
+ SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
+ SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0",
+ SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0",
+ SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
+ SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
+ { "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
+ { "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 },
+ { "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 },
+ { "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 },
+ { "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 },
+ { "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
+ { "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
+ { "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
+ { "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
+ { "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 },
+ { "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
+ { "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
+ { "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
+ { "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 },
+#if defined( __sgi ) || defined( __hpux )
+ { "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 },
+#endif /* __sgi || __hpux */
+ { "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
+ { "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 },
+ { "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/
+ { "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 },
+ { "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 },
+ /* Unreliable source, depends on system usage */
+ { "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 },
+ { "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 },
+ { "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 },
+ { "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 },
+ { "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 },
+ { "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 },
+ { "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 },
+ { "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 },
+ { "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
+ { "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
+ /* pstat is your friend */
+ { "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 },
+#ifdef __sgi
+ { "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
+#endif /* __sgi */
+#ifdef __hpux
+ { "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
+#endif /* __hpux */
+ { "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 },
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0",
+ SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
+ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0",
+ SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
+ { "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
+ { "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
+ { "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 },
+ { "/usr/sbin/ripquery", "-nw 1 127.0.0.1",
+ SC(0.1), NULL, 0, 0, 0, 0 },
+ { "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
+ { "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
+ { "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
+ { "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 },
+ /* This is very environment-dependent. If network traffic is low, it'll
+ * probably time out before delivering 5 packets, which is OK because
+ * it'll probably be fixed stuff like ARP anyway */
+ { "/usr/sbin/advfsstat", "-b usr_domain",
+ SC(SC_0), NULL, 0, 0, 0, 0},
+ { "/usr/sbin/advfsstat", "-l 2 usr_domain",
+ SC(0.5), NULL, 0, 0, 0, 0},
+ { "/usr/sbin/advfsstat", "-p usr_domain",
+ SC(SC_0), NULL, 0, 0, 0, 0},
+ /* This is a complex and screwball program. Some systems have things
+ * like rX_dmn, x = integer, for RAID systems, but the statistics are
+ * pretty dodgy */
+#ifdef __QNXNTO__
+ { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
+ NULL, 0, 0, 0, 0 },
+#endif
+#if 0
+ /* The following aren't enabled since they're somewhat slow and not very
+ * unpredictable, however they give an indication of the sort of sources
+ * you can use (for example the finger might be more useful on a
+ * firewalled internal network) */
+ { "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
+ { "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
+ SC(0.9), NULL, 0, 0, 0, 0 },
+ { "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
+#endif /* 0 */
+ { NULL, NULL, 0, NULL, 0, 0, 0, 0 }
+};
+
+static byte *gather_buffer; /* buffer for gathering random noise */
+static int gather_buffer_size; /* size of the memory buffer */
+static uid_t gatherer_uid;
+
+/* The message structure used to communicate with the parent */
+typedef struct {
+ int usefulness; /* usefulness of data */
+ int ndata; /* valid bytes in data */
+ char data[500]; /* gathered data */
+} GATHER_MSG;
+
+#ifndef HAVE_WAITPID
+static pid_t
+waitpid(pid_t pid, int *statptr, int options)
+{
+#ifdef HAVE_WAIT4
+ return wait4(pid, statptr, options, NULL);
+#else
+ /* If wait4 is also not available, try wait3 for SVR3 variants */
+ /* Less ideal because can't actually request a specific pid */
+ /* For that reason, first check to see if pid is for an */
+ /* existing process. */
+ int tmp_pid, dummystat;;
+ if (kill(pid, 0) == -1) {
+ errno = ECHILD;
+ return -1;
+ }
+ if (statptr == NULL)
+ statptr = &dummystat;
+ while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
+ (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
+ ;
+ return tmp_pid;
+#endif
+}
+#endif
+
+/* Under SunOS popen() doesn't record the pid of the child process. When
+ * pclose() is called, instead of calling waitpid() for the correct child, it
+ * calls wait() repeatedly until the right child is reaped. The problem is
+ * that this reaps any other children that happen to have died at that
+ * moment, and when their pclose() comes along, the process hangs forever.
+ * The fix is to use a wrapper for popen()/pclose() which saves the pid in
+ * the dataSources structure (code adapted from GNU-libc's popen() call).
+ *
+ * Aut viam inveniam aut faciam */
+
+static FILE *
+my_popen(struct RI *entry)
+{
+ int pipedes[2];
+ FILE *stream;
+
+ /* Create the pipe */
+ if (pipe(pipedes) < 0)
+ return (NULL);
+
+ /* Fork off the child ("vfork() is like an OS orgasm. All OS's want to
+ * do it, but most just end up faking it" - Chris Wedgwood). If your OS
+ * supports it, you should try to use vfork() here because it's somewhat
+ * more efficient */
+#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
+ defined(__hpux)
+ entry->pid = vfork();
+#else /* */
+ entry->pid = fork();
+#endif /* Unixen which have vfork() */
+ if (entry->pid == (pid_t) - 1) {
+ /* The fork failed */
+ close(pipedes[0]);
+ close(pipedes[1]);
+ return (NULL);
+ }
+
+ if (entry->pid == (pid_t) 0) {
+ struct passwd *passwd;
+
+ /* We are the child. Make the read side of the pipe be stdout */
+ if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
+ exit(127);
+
+ /* Now that everything is set up, give up our permissions to make
+ * sure we don't read anything sensitive. If the getpwnam() fails,
+ * we default to -1, which is usually nobody */
+ if (gatherer_uid == (uid_t)-1 && \
+ (passwd = getpwnam("nobody")) != NULL)
+ gatherer_uid = passwd->pw_uid;
+
+ setuid(gatherer_uid);
+
+ /* Close the pipe descriptors */
+ close(pipedes[STDIN_FILENO]);
+ close(pipedes[STDOUT_FILENO]);
+
+ /* Try and exec the program */
+ execl(entry->path, entry->path, entry->arg, NULL);
+
+ /* Die if the exec failed */
+ exit(127);
+ }
+
+ /* We are the parent. Close the irrelevant side of the pipe and open
+ * the relevant side as a new stream. Mark our side of the pipe to
+ * close on exec, so new children won't see it */
+ close(pipedes[STDOUT_FILENO]);
+
+#ifdef FD_CLOEXEC
+ fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
+#endif
+
+ stream = fdopen(pipedes[STDIN_FILENO], "r");
+
+ if (stream == NULL) {
+ int savedErrno = errno;
+
+ /* The stream couldn't be opened or the child structure couldn't be
+ * allocated. Kill the child and close the other side of the pipe */
+ kill(entry->pid, SIGKILL);
+ if (stream == NULL)
+ close(pipedes[STDOUT_FILENO]);
+ else
+ fclose(stream);
+
+ waitpid(entry->pid, NULL, 0);
+
+ entry->pid = 0;
+ errno = savedErrno;
+ return (NULL);
+ }
+
+ return (stream);
+}
+
+static int
+my_pclose(struct RI *entry)
+{
+ int status = 0;
+
+ if (fclose(entry->pipe))
+ return (-1);
+
+ /* We ignore the return value from the process because some
+ programs return funny values which would result in the input
+ being discarded even if they executed successfully. This isn't
+ a problem because the result data size threshold will filter
+ out any programs which exit with a usage message without
+ producing useful output. */
+ if (waitpid(entry->pid, NULL, 0) != entry->pid)
+ status = -1;
+
+ entry->pipe = NULL;
+ entry->pid = 0;
+ return (status);
+}
+
+
+/* Unix slow poll (without special support for Linux)
+ *
+ * If a few of the randomness sources create a large amount of output then
+ * the slowPoll() stops once the buffer has been filled (but before all the
+ * randomness sources have been sucked dry) so that the 'usefulness' factor
+ * remains below the threshold. For this reason the gatherer buffer has to
+ * be fairly sizeable on moderately loaded systems. This is something of a
+ * bug since the usefulness should be influenced by the amount of output as
+ * well as the source type */
+
+
+static int
+slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
+{
+ int moreSources;
+ struct timeval tv;
+ fd_set fds;
+#if defined( __hpux )
+ size_t maxFD = 0;
+#else
+ int maxFD = 0;
+#endif /* OS-specific brokenness */
+ int bufPos, i, usefulness = 0;
+ int last_so_far = 0;
+ int any_need_entropy = 0;
+ int delay;
+ int rc;
+
+ /* Fire up each randomness source */
+ FD_ZERO(&fds);
+ for (i = 0; dataSources[i].path != NULL; i++) {
+ /* Since popen() is a fairly heavy function, we check to see whether
+ * the executable exists before we try to run it */
+ if (access(dataSources[i].path, X_OK)) {
+ if( dbgfp && dbgall )
+ fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
+ dataSources[i].hasAlternative ?
+ ", has alternatives" : "");
+ dataSources[i].pipe = NULL;
+ }
+ else
+ dataSources[i].pipe = my_popen(&dataSources[i]);
+
+ if (dataSources[i].pipe != NULL) {
+ dataSources[i].pipeFD = fileno(dataSources[i].pipe);
+ if (dataSources[i].pipeFD > maxFD)
+ maxFD = dataSources[i].pipeFD;
+
+#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
+ fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
+#else
+#error O_NONBLOCK is missing
+#endif
+ /* FIXME: We need to make sure that the fd is less than
+ FD_SETSIZE. */
+ FD_SET(dataSources[i].pipeFD, &fds);
+ dataSources[i].length = 0;
+
+ /* If there are alternatives for this command, don't try and
+ * execute them */
+ while (dataSources[i].hasAlternative) {
+ if( dbgfp && dbgall )
+ fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
+ i++;
+ }
+ }
+ }
+
+
+ /* Suck all the data we can get from each of the sources */
+ bufPos = 0;
+ moreSources = 1;
+ delay = 0; /* Return immediately (well, after 100ms) the first time. */
+ while (moreSources && bufPos <= gather_buffer_size) {
+ /* Wait for data to become available from any of the sources, with a
+ * timeout of 10 seconds. This adds even more randomness since data
+ * becomes available in a nondeterministic fashion. Kudos to HP's QA
+ * department for managing to ship a select() which breaks its own
+ * prototype */
+ tv.tv_sec = delay;
+ tv.tv_usec = delay? 0 : 100000;
+
+#if defined( __hpux ) && ( OS_VERSION == 9 )
+ rc = select(maxFD + 1, (int *)&fds, NULL, NULL, &tv);
+#else /* */
+ rc = select(maxFD + 1, &fds, NULL, NULL, &tv);
+#endif /* __hpux */
+ if (rc == -1)
+ break; /* Ooops; select failed. */
+
+ if (!rc)
+ {
+ /* FIXME: Because we run several tools at once it is
+ unlikely that we will see a block in select at all. */
+ if (!any_need_entropy
+ || last_so_far != (gather_buffer_size - bufPos) )
+ {
+ last_so_far = gather_buffer_size - bufPos;
+ _gcry_random_progress ("need_entropy", 'X',
+ last_so_far,
+ gather_buffer_size);
+ any_need_entropy = 1;
+ }
+ delay = 10; /* Use 10 seconds henceforth. */
+ /* Note that the fd_set is setup again at the end of this loop. */
+ }
+
+ /* One of the sources has data available, read it into the buffer */
+ for (i = 0; dataSources[i].path != NULL; i++) {
+ if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
+ size_t noBytes;
+
+ if ((noBytes = fread(gather_buffer + bufPos, 1,
+ gather_buffer_size - bufPos,
+ dataSources[i].pipe)) == 0) {
+ if (my_pclose(&dataSources[i]) == 0) {
+ int total = 0;
+
+ /* Try and estimate how much entropy we're getting
+ * from a data source */
+ if (dataSources[i].usefulness) {
+ if (dataSources[i].usefulness < 0)
+ total = (dataSources[i].length + 999)
+ / -dataSources[i].usefulness;
+ else
+ total = dataSources[i].length
+ / dataSources[i].usefulness;
+ }
+ if( dbgfp )
+ fprintf(dbgfp,
+ "%s %s contributed %d bytes, "
+ "usefulness = %d\n", dataSources[i].path,
+ (dataSources[i].arg != NULL) ?
+ dataSources[i].arg : "",
+ dataSources[i].length, total);
+ if( dataSources[i].length )
+ usefulness += total;
+ }
+ dataSources[i].pipe = NULL;
+ }
+ else {
+ int currPos = bufPos;
+ int endPos = bufPos + noBytes;
+
+ /* Run-length compress the input byte sequence */
+ while (currPos < endPos) {
+ int ch = gather_buffer[currPos];
+
+ /* If it's a single byte, just copy it over */
+ if (ch != gather_buffer[currPos + 1]) {
+ gather_buffer[bufPos++] = ch;
+ currPos++;
+ }
+ else {
+ int count = 0;
+
+ /* It's a run of repeated bytes, replace them
+ * with the byte count mod 256 */
+ while ((ch == gather_buffer[currPos])
+ && currPos < endPos) {
+ count++;
+ currPos++;
+ }
+ gather_buffer[bufPos++] = count;
+ noBytes -= count - 1;
+ }
+ }
+
+ /* Remember the number of (compressed) bytes of input we
+ * obtained */
+ dataSources[i].length += noBytes;
+ }
+ }
+ }
+
+ /* Check if there is more input available on any of the sources */
+ moreSources = 0;
+ FD_ZERO(&fds);
+ for (i = 0; dataSources[i].path != NULL; i++) {
+ if (dataSources[i].pipe != NULL) {
+ FD_SET(dataSources[i].pipeFD, &fds);
+ moreSources = 1;
+ }
+ }
+ }
+
+ if (any_need_entropy)
+ _gcry_random_progress ("need_entropy", 'X',
+ gather_buffer_size,
+ gather_buffer_size);
+
+ if( dbgfp ) {
+ fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
+ fflush(dbgfp);
+ }
+ *nbytes = bufPos;
+ return usefulness;
+}
+
+/****************
+ * Start the gatherer process which writes messages of
+ * type GATHERER_MSG to pipedes
+ */
+static void
+start_gatherer( int pipefd )
+{
+ FILE *dbgfp = NULL;
+ int dbgall;
+
+ {
+ const char *s = getenv("GCRYPT_RNDUNIX_DBG");
+ if( s ) {
+ dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
+ if( !dbgfp )
+ log_info("can't open debug file `%s': %s\n",
+ s, strerror(errno) );
+ else
+ fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
+ }
+ dbgall = !!getenv("GCRYPT_RNDUNIX_DBGALL");
+ }
+ /* close all files but the ones we need */
+ { int nmax, n1, n2, i;
+#ifdef _SC_OPEN_MAX
+ if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
+# ifdef _POSIX_OPEN_MAX
+ nmax = _POSIX_OPEN_MAX;
+# else
+ nmax = 20; /* assume a reasonable value */
+# endif
+ }
+ /* AIX returns INT32_MAX instead of a proper value. We assume that
+ * this is always an error and use a reasonable value. */
+# ifdef INT32_MAX
+ if (nmax == INT32_MAX)
+ nmax = 20;
+# endif
+#else /*!_SC_OPEN_MAX*/
+ nmax = 20; /* assume a reasonable value */
+#endif /*!_SC_OPEN_MAX*/
+ n1 = fileno( stderr );
+ n2 = dbgfp? fileno( dbgfp ) : -1;
+ for(i=0; i < nmax; i++ ) {
+ if( i != n1 && i != n2 && i != pipefd )
+ close(i);
+ }
+ errno = 0;
+ }
+
+
+ /* Set up the buffer. Not ethat we use a plain standard malloc here. */
+ gather_buffer_size = GATHER_BUFSIZE;
+ gather_buffer = malloc( gather_buffer_size );
+ if( !gather_buffer ) {
+ log_error("out of core while allocating the gatherer buffer\n");
+ exit(2);
+ }
+
+ /* Reset the SIGC(H)LD handler to the system default. This is necessary
+ * because if the program which cryptlib is a part of installs its own
+ * SIGC(H)LD handler, it will end up reaping the cryptlib children before
+ * cryptlib can. As a result, my_pclose() will call waitpid() on a
+ * process which has already been reaped by the installed handler and
+ * return an error, so the read data won't be added to the randomness
+ * pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and
+ * the BSD/Posix SIGCHLD, so we need to handle either possibility */
+#ifdef SIGCLD
+ signal(SIGCLD, SIG_DFL);
+#else
+ signal(SIGCHLD, SIG_DFL);
+#endif
+
+ fclose(stderr); /* Arrghh!! It's Stuart code!! */
+
+ /* Mary goes to Berkeley: NetBSD emits warnings if the standard
+ descriptors are not open when running setuid program. Thus we
+ connect them to the bitbucket if they are not already open. */
+ {
+ struct stat statbuf;
+
+ if (fstat (STDIN_FILENO, &statbuf) == -1 && errno == EBADF)
+ open ("/dev/null",O_RDONLY);
+ if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
+ open ("/dev/null",O_WRONLY);
+ if (fstat (STDERR_FILENO, &statbuf) == -1 && errno == EBADF)
+ open ("/dev/null",O_WRONLY);
+ }
+
+ for(;;) {
+ GATHER_MSG msg;
+ size_t nbytes;
+ const char *p;
+
+ msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
+ p = (const char*)gather_buffer;
+ while( nbytes ) {
+ msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
+ memcpy( msg.data, p, msg.ndata );
+ nbytes -= msg.ndata;
+ p += msg.ndata;
+
+ while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
+ if( errno == EINTR )
+ continue;
+ if( errno == EAGAIN ) {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+ select(0, NULL, NULL, NULL, &tv);
+ continue;
+ }
+ if( errno == EPIPE ) /* parent has exited, so give up */
+ exit(0);
+
+ /* we can't do very much here because stderr is closed */
+ if( dbgfp )
+ fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
+ strerror(errno) );
+ /* we start a new poll to give the system some time */
+ nbytes = 0;
+ break;
+ }
+ }
+ }
+ /* we are killed when the parent dies */
+}
+
+
+static int
+read_a_msg( int fd, GATHER_MSG *msg )
+{
+ char *buffer = (char*)msg;
+ size_t length = sizeof( *msg );
+ int n;
+
+ do {
+ do {
+ n = read(fd, buffer, length );
+ } while( n == -1 && errno == EINTR );
+ if( n == -1 )
+ return -1;
+ buffer += n;
+ length -= n;
+ } while( length );
+ return 0;
+}
+
+
+/****************
+ * Using a level of 0 should never block and better add nothing
+ * to the pool. So this is just a dummy for this gatherer.
+ */
+int
+_gcry_rndunix_gather_random (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level )
+{
+ static pid_t gatherer_pid = 0;
+ static int pipedes[2];
+ GATHER_MSG msg;
+ size_t n;
+
+ if( !level )
+ return 0;
+
+ if( !gatherer_pid ) {
+ /* Make sure we are not setuid. */
+ if ( getuid() != geteuid() )
+ BUG();
+ /* time to start the gatherer process */
+ if( pipe( pipedes ) ) {
+ log_error("pipe() failed: %s\n", strerror(errno));
+ return -1;
+ }
+ gatherer_pid = fork();
+ if( gatherer_pid == -1 ) {
+ log_error("can't for gatherer process: %s\n", strerror(errno));
+ return -1;
+ }
+ if( !gatherer_pid ) {
+ start_gatherer( pipedes[1] );
+ /* oops, can't happen */
+ return -1;
+ }
+ }
+
+ /* now read from the gatherer */
+ while( length ) {
+ int goodness;
+ unsigned long subtract;
+
+ if( read_a_msg( pipedes[0], &msg ) ) {
+ log_error("reading from gatherer pipe failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+
+ if( level > 1 ) {
+ if( msg.usefulness > 30 )
+ goodness = 100;
+ else if ( msg.usefulness )
+ goodness = msg.usefulness * 100 / 30;
+ else
+ goodness = 0;
+ }
+ else if( level ) {
+ if( msg.usefulness > 15 )
+ goodness = 100;
+ else if ( msg.usefulness )
+ goodness = msg.usefulness * 100 / 15;
+ else
+ goodness = 0;
+ }
+ else
+ goodness = 100; /* goodness of level 0 is always 100 % */
+
+ n = msg.ndata;
+ if( n > length )
+ n = length;
+ (*add)( msg.data, n, origin );
+
+ /* this is the trick how we cope with the goodness */
+ subtract = (unsigned long)n * goodness / 100;
+ /* subtract at least 1 byte to avoid infinite loops */
+ length -= subtract ? subtract : 1;
+ }
+
+ return 0;
+}
diff --git a/comm/third_party/libgcrypt/random/rndw32.c b/comm/third_party/libgcrypt/random/rndw32.c
new file mode 100644
index 0000000000..b3f63d2072
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndw32.c
@@ -0,0 +1,1030 @@
+/* rndw32.c - W32 entropy gatherer
+ * Copyright (C) 1999, 2000, 2002, 2003, 2007,
+ * 2010 Free Software Foundation, Inc.
+ * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006
+ *
+ * This file is part of Libgcrypt.
+ *
+ *************************************************************************
+ * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann.
+ * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this
+ * copyright notice:
+ *
+ * This module is part of the cryptlib continuously seeded pseudorandom
+ * number generator. For usage conditions, see lib_rand.c
+ *
+ * [Here is the notice from lib_rand.c, which is now called dev_sys.c]
+ *
+ * This module and the misc/rnd*.c modules represent the cryptlib
+ * continuously seeded pseudorandom number generator (CSPRNG) as described in
+ * my 1998 Usenix Security Symposium paper "The generation of random numbers
+ * for cryptographic purposes".
+ *
+ * The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
+ * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
+ * modules 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
+ * and this permission notice in its entirety.
+ *
+ * 2. Redistributions in binary form must reproduce the copyright notice in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * 3. A copy of any bugfixes or enhancements made must be provided to the
+ * author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
+ * baseline version of the code.
+ *
+ * ALTERNATIVELY, the code may be distributed under the terms of the
+ * GNU Lesser General Public License, version 2.1 or any later version
+ * published by the Free Software Foundation, in which case the
+ * provisions of the GNU LGPL are required INSTEAD OF the above
+ * restrictions.
+ *
+ * Although not required under the terms of the LGPL, it would still
+ * be nice if you could make any changes available to the author to
+ * allow a consistent code base to be maintained.
+ *************************************************************************
+ * The above alternative was changed from GPL to LGPL on 2007-08-22 with
+ * permission from Peter Gutmann:
+ *==========
+ From: pgut001 <pgut001@cs.auckland.ac.nz>
+ Subject: Re: LGPL for the windows entropy gatherer
+ To: wk@gnupg.org
+ Date: Wed, 22 Aug 2007 03:05:42 +1200
+
+ Hi,
+
+ >As of now libgcrypt is GPL under Windows due to that module and some people
+ >would really like to see it under LGPL too. Can you do such a license change
+ >to LGPL version 2? Note that LGPL give the user the option to relicense it
+ >under GPL, so the change would be pretty easy and backwar compatible.
+
+ Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy
+ code as well, but Ian asked for LGPL as an option so as of the next release
+ I'll have LGPL in there. You can consider it to be retroactive, so your
+ current version will be LGPLd as well.
+
+ Peter.
+ *==========
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#ifdef __GNUC__
+#include <stdint.h>
+#endif
+
+#include <winsock2.h>
+#include <windows.h>
+
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+
+/* Definitions which are missing from the current GNU Windows32Api. */
+#ifndef IOCTL_DISK_PERFORMANCE
+#define IOCTL_DISK_PERFORMANCE 0x00070020
+#endif
+
+/* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger
+ value in a newer release. So we use a far larger value. */
+#define SIZEOF_DISK_PERFORMANCE_STRUCT 256
+
+/* We don't include wincrypt.h so define it here. */
+#define HCRYPTPROV HANDLE
+
+
+/* When we query the performance counters, we allocate an initial buffer and
+ * then reallocate it as required until RegQueryValueEx() stops returning
+ * ERROR_MORE_DATA. The following values define the initial buffer size and
+ * step size by which the buffer is increased
+ */
+#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */
+#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */
+
+
+/* The number of bytes to read from the system RNG on each slow poll. */
+#define SYSTEMRNG_BYTES 64
+
+/* Intel Chipset CSP type and name */
+#define PROV_INTEL_SEC 22
+#define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
+
+
+
+
+/* Type definitions for function pointers to call NetAPI32 functions. */
+typedef DWORD (WINAPI *NETSTATISTICSGET)(LPWSTR szServer, LPWSTR szService,
+ DWORD dwLevel, DWORD dwOptions,
+ LPBYTE *lpBuffer);
+typedef DWORD (WINAPI *NETAPIBUFFERSIZE)(LPVOID lpBuffer, LPDWORD cbBuffer);
+typedef DWORD (WINAPI *NETAPIBUFFERFREE)(LPVOID lpBuffer);
+
+/* Type definitions for function pointers to call native NT functions. */
+typedef DWORD (WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD systemInformationClass,
+ PVOID systemInformation,
+ ULONG systemInformationLength,
+ PULONG returnLength);
+typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS)
+ (HANDLE processHandle, DWORD processInformationClass,
+ PVOID processInformation, ULONG processInformationLength,
+ PULONG returnLength);
+typedef DWORD (WINAPI *NTPOWERINFORMATION)
+ (DWORD powerInformationClass, PVOID inputBuffer,
+ ULONG inputBufferLength, PVOID outputBuffer, ULONG outputBufferLength );
+
+/* Type definitions for function pointers to call CryptoAPI functions. */
+typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv,
+ LPCTSTR pszContainer,
+ LPCTSTR pszProvider,
+ DWORD dwProvType,
+ DWORD dwFlags);
+typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,
+ BYTE *pbBuffer);
+typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
+
+/* Somewhat alternative functionality available as a direct call, for
+ Windows XP and newer. This is the CryptoAPI RNG, which isn't anywhere
+ near as good as the HW RNG, but we use it if it's present on the basis
+ that at least it can't make things any worse. This direct access version
+ is only available under Windows XP, we don't go out of our way to access
+ the more general CryptoAPI one since the main purpose of using it is to
+ take advantage of any possible future hardware RNGs that may be added,
+ for example via TCPA devices. */
+typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer,
+ ULONG RandomBufferLength);
+
+
+
+/* MBM data structures, originally by Alexander van Kaam, converted to C by
+ Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu> */
+#define BusType char
+#define SMBType char
+#define SensorType char
+
+typedef struct
+{
+ SensorType iType; /* Type of sensor. */
+ int Count; /* Number of sensor for that type. */
+} SharedIndex;
+
+typedef struct
+{
+ SensorType ssType; /* Type of sensor */
+ unsigned char ssName[12]; /* Name of sensor */
+ char sspadding1[3]; /* Padding of 3 bytes */
+ double ssCurrent; /* Current value */
+ double ssLow; /* Lowest readout */
+ double ssHigh; /* Highest readout */
+ long ssCount; /* Total number of readout */
+ char sspadding2[4]; /* Padding of 4 bytes */
+ long double ssTotal; /* Total amount of all readouts */
+ char sspadding3[6]; /* Padding of 6 bytes */
+ double ssAlarm1; /* Temp & fan: high alarm; voltage: % off */
+ double ssAlarm2; /* Temp: low alarm */
+} SharedSensor;
+
+typedef struct
+{
+ short siSMB_Base; /* SMBus base address */
+ BusType siSMB_Type; /* SMBus/Isa bus used to access chip */
+ SMBType siSMB_Code; /* SMBus sub type, Intel, AMD or ALi */
+ char siSMB_Addr; /* Address of sensor chip on SMBus */
+ unsigned char siSMB_Name[41]; /* Nice name for SMBus */
+ short siISA_Base; /* ISA base address of sensor chip on ISA */
+ int siChipType; /* Chip nr, connects with Chipinfo.ini */
+ char siVoltageSubType; /* Subvoltage option selected */
+} SharedInfo;
+
+typedef struct
+{
+ double sdVersion; /* Version number (example: 51090) */
+ SharedIndex sdIndex[10]; /* Sensor index */
+ SharedSensor sdSensor[100]; /* Sensor info */
+ SharedInfo sdInfo; /* Misc.info */
+ unsigned char sdStart[41]; /* Start time */
+
+ /* We don't use the next two fields both because they're not random
+ and because it provides a nice safety margin in case of data size
+ mis- estimates (we always under-estimate the buffer size). */
+#if 0
+ unsigned char sdCurrent[41]; /* Current time */
+ unsigned char sdPath[256]; /* MBM path */
+#endif /*0*/
+} SharedData;
+
+
+
+/* One time initialized handles and function pointers. We use dynamic
+ loading of the DLLs to do without them in case libgcrypt does not
+ need any random. */
+static HANDLE hNetAPI32;
+static NETSTATISTICSGET pNetStatisticsGet;
+static NETAPIBUFFERSIZE pNetApiBufferSize;
+static NETAPIBUFFERFREE pNetApiBufferFree;
+
+static HANDLE hNTAPI;
+static NTQUERYSYSTEMINFORMATION pNtQuerySystemInformation;
+static NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess;
+static NTPOWERINFORMATION pNtPowerInformation;
+
+static HANDLE hAdvAPI32;
+static CRYPTACQUIRECONTEXT pCryptAcquireContext;
+static CRYPTGENRANDOM pCryptGenRandom;
+static CRYPTRELEASECONTEXT pCryptReleaseContext;
+static RTLGENRANDOM pRtlGenRandom;
+
+
+/* Other module global variables. */
+static int system_rng_available; /* Whether a system RNG is available. */
+static HCRYPTPROV hRNGProv; /* Handle to Intel RNG CSP. */
+
+/* The debug flag. Debugging is enabled if the value of the envvar
+ * GCRY_RNDW32_DBG is a positive number.*/
+static int debug_me;
+
+static int system_is_w2000; /* True if running on W2000. */
+
+
+
+/* Try and connect to the system RNG if there's one present. */
+static void
+init_system_rng (void)
+{
+ system_rng_available = 0;
+ hRNGProv = NULL;
+
+ hAdvAPI32 = GetModuleHandle ("AdvAPI32.dll");
+ if (!hAdvAPI32)
+ return;
+
+ pCryptAcquireContext = (CRYPTACQUIRECONTEXT)
+ GetProcAddress (hAdvAPI32, "CryptAcquireContextA");
+ pCryptGenRandom = (CRYPTGENRANDOM)
+ GetProcAddress (hAdvAPI32, "CryptGenRandom");
+ pCryptReleaseContext = (CRYPTRELEASECONTEXT)
+ GetProcAddress (hAdvAPI32, "CryptReleaseContext");
+
+ /* Get a pointer to the native randomness function if it's available.
+ This isn't exported by name, so we have to get it by ordinal. */
+ pRtlGenRandom = (RTLGENRANDOM)
+ GetProcAddress (hAdvAPI32, "SystemFunction036");
+
+ /* Try and connect to the PIII RNG CSP. The AMD 768 southbridge (from
+ the 760 MP chipset) also has a hardware RNG, but there doesn't appear
+ to be any driver support for this as there is for the Intel RNG so we
+ can't do much with it. OTOH the Intel RNG is also effectively dead
+ as well, mostly due to virtually nonexistent support/marketing by
+ Intel, it's included here mostly for form's sake. */
+ if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext
+ || !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV,
+ PROV_INTEL_SEC, 0) )
+ && !pRtlGenRandom)
+ {
+ hAdvAPI32 = NULL;
+ }
+ else
+ system_rng_available = 1;
+}
+
+
+/* Read data from the system RNG if availavle. */
+static void
+read_system_rng (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins requester)
+{
+ BYTE buffer[ SYSTEMRNG_BYTES + 8 ];
+ int quality = 0;
+
+ if (!system_rng_available)
+ return;
+
+ /* Read SYSTEMRNG_BYTES bytes from the system RNG. We don't rely on
+ this for all our randomness requirements (particularly the
+ software RNG) in case it's broken in some way. */
+ if (hRNGProv)
+ {
+ if (pCryptGenRandom (hRNGProv, SYSTEMRNG_BYTES, buffer))
+ quality = 80;
+ }
+ else if (pRtlGenRandom)
+ {
+ if ( pRtlGenRandom (buffer, SYSTEMRNG_BYTES))
+ quality = 50;
+ }
+ if (quality > 0)
+ {
+ if (debug_me)
+ log_debug ("rndw32#read_system_rng: got %d bytes of quality %d\n",
+ SYSTEMRNG_BYTES, quality);
+ (*add) (buffer, SYSTEMRNG_BYTES, requester);
+ wipememory (buffer, SYSTEMRNG_BYTES);
+ }
+}
+
+
+/* Read data from MBM. This communicates via shared memory, so all we
+ need to do is map a file and read the data out. */
+static void
+read_mbm_data (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins requester)
+{
+ HANDLE hMBMData;
+ SharedData *mbmDataPtr;
+
+ hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, "$M$B$M$5$S$D$" );
+ if (hMBMData)
+ {
+ mbmDataPtr = (SharedData*)MapViewOfFile (hMBMData, FILE_MAP_READ,0,0,0);
+ if (mbmDataPtr)
+ {
+ if (debug_me)
+ log_debug ("rndw32#read_mbm_data: got %d bytes\n",
+ (int)sizeof (SharedData));
+ (*add) (mbmDataPtr, sizeof (SharedData), requester);
+ UnmapViewOfFile (mbmDataPtr);
+ }
+ CloseHandle (hMBMData);
+ }
+}
+
+
+/* Fallback method using the registry to poll the statistics. */
+static void
+registry_poll (void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins requester)
+{
+ static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
+ int iterations;
+ DWORD dwSize, status;
+ PERF_DATA_BLOCK *pPerfData;
+
+ /* Get information from the system performance counters. This can take a
+ few seconds to do. In some environments the call to RegQueryValueEx()
+ can produce an access violation at some random time in the future, in
+ some cases adding a short delay after the following code block makes
+ the problem go away. This problem is extremely difficult to
+ reproduce, I haven't been able to get it to occur despite running it
+ on a number of machines. MS knowledge base article Q178887 covers
+ this type of problem, it's typically caused by an external driver or
+ other program that adds its own values under the
+ HKEY_PERFORMANCE_DATA key. The NT kernel, via Advapi32.dll, calls the
+ required external module to map in the data inside an SEH try/except
+ block, so problems in the module's collect function don't pop up until
+ after it has finished, so the fault appears to occur in Advapi32.dll.
+ There may be problems in the NT kernel as well though, a low-level
+ memory checker indicated that ExpandEnvironmentStrings() in
+ Kernel32.dll, called an interminable number of calls down inside
+ RegQueryValueEx(), was overwriting memory (it wrote twice the
+ allocated size of a buffer to a buffer allocated by the NT kernel).
+ OTOH this could be coming from the external module calling back into
+ the kernel, which eventually causes the problem described above.
+
+ Possibly as an extension of the problem that the krnlWaitSemaphore()
+ call above works around, running two instances of cryptlib (e.g. two
+ applications that use it) under NT4 can result in one of them hanging
+ in the RegQueryValueEx() call. This happens only under NT4 and is
+ hard to reproduce in any consistent manner.
+
+ One workaround that helps a bit is to read the registry as a remote
+ (rather than local) registry, it's possible that the use of a network
+ RPC call isolates the calling app from the problem in that whatever
+ service handles the RPC is taking the hit and not affecting the
+ calling app. Since this would require another round of extensive
+ testing to verify and the NT native API call is working fine, we'll
+ stick with the native API call for now.
+
+ Some versions of NT4 had a problem where the amount of data returned
+ was mis-reported and would never settle down, because of this the code
+ below includes a safety-catch that bails out after 10 attempts have
+ been made, this results in no data being returned but at does ensure
+ that the thread will terminate.
+
+ In addition to these problems the code in RegQueryValueEx() that
+ estimates the amount of memory required to return the performance
+ counter information isn't very accurate (it's much worse than the
+ "slightly-inaccurate" level that the MS docs warn about, it's usually
+ wildly off) since it always returns a worst-case estimate which is
+ usually nowhere near the actual amount required. For example it may
+ report that 128K of memory is required, but only return 64K of data.
+
+ Even worse than the registry-based performance counters is the
+ performance data helper (PDH) shim that tries to make the counters
+ look like the old Win16 API (which is also used by Win95). Under NT
+ this can consume tens of MB of memory and huge amounts of CPU time
+ while it gathers its data, and even running once can still consume
+ about 1/2MB of memory */
+ if (getenv ("GCRYPT_RNDW32_NOPERF"))
+ {
+ static int shown;
+
+ if (!shown)
+ {
+ shown = 1;
+ log_info ("note: get performance data has been disabled\n");
+ }
+ }
+ else
+ {
+ pPerfData = xmalloc (cbPerfData);
+ for (iterations=0; iterations < 10; iterations++)
+ {
+ dwSize = cbPerfData;
+ if ( debug_me )
+ log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
+
+ status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
+ NULL, (LPBYTE) pPerfData, &dwSize);
+ if (status == ERROR_SUCCESS)
+ {
+ if (!memcmp (pPerfData->Signature, L"PERF", 8))
+ (*add) ( pPerfData, dwSize, requester );
+ else
+ log_debug ("rndw32: no PERF signature\n");
+ break;
+ }
+ else if (status == ERROR_MORE_DATA)
+ {
+ cbPerfData += PERFORMANCE_BUFFER_STEP;
+ pPerfData = xrealloc (pPerfData, cbPerfData);
+ }
+ else
+ {
+ static int been_here;
+
+ /* Silence the error message. In particular under Wine (as
+ of 2008) we would get swamped with such diagnotiscs. One
+ such diagnotiscs should be enough. */
+ if (been_here != status)
+ {
+ been_here = status;
+ log_debug ("rndw32: get performance data problem: ec=%ld\n",
+ status);
+ }
+ break;
+ }
+ }
+ xfree (pPerfData);
+ }
+
+ /* Although this isn't documented in the Win32 API docs, it's necessary
+ to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
+ implicitly opened on the first call to RegQueryValueEx()). If this
+ isn't done then any system components which provide performance data
+ can't be removed or changed while the handle remains active. */
+ RegCloseKey (HKEY_PERFORMANCE_DATA);
+}
+
+
+static void
+slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
+ enum random_origins requester )
+{
+ static int is_initialized = 0;
+ static int is_workstation = 1;
+ HANDLE hDevice;
+ DWORD dwType, dwSize, dwResult;
+ ULONG ulSize;
+ int drive_no, status;
+ int no_results = 0;
+ void *buffer;
+
+ if ( !is_initialized )
+ {
+ HKEY hKey;
+
+ if ( debug_me )
+ log_debug ("rndw32#slow_gatherer: init toolkit\n" );
+ /* Find out whether this is an NT server or workstation if necessary */
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
+ 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ BYTE szValue[32 + 8];
+ dwSize = 32;
+
+ if ( debug_me )
+ log_debug ("rndw32#slow_gatherer: check product options\n" );
+
+ status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
+ szValue, &dwSize);
+ if (status == ERROR_SUCCESS && stricmp ((char*)szValue, "WinNT"))
+ {
+ /* Note: There are (at least) three cases for ProductType:
+ WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
+ NT Server acting as a Domain Controller. */
+ is_workstation = 0;
+ if ( debug_me )
+ log_debug ("rndw32: this is a NT server\n");
+ }
+ RegCloseKey (hKey);
+ }
+
+ /* The following are fixed for the lifetime of the process so we
+ only add them once */
+ /* readPnPData (); - we have not implemented that. */
+
+ /* Initialize the NetAPI32 function pointers if necessary */
+ hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
+ if (hNetAPI32)
+ {
+ if (debug_me)
+ log_debug ("rndw32#slow_gatherer: netapi32 loaded\n" );
+ pNetStatisticsGet = (NETSTATISTICSGET)
+ GetProcAddress (hNetAPI32, "NetStatisticsGet");
+ pNetApiBufferSize = (NETAPIBUFFERSIZE)
+ GetProcAddress (hNetAPI32, "NetApiBufferSize");
+ pNetApiBufferFree = (NETAPIBUFFERFREE)
+ GetProcAddress (hNetAPI32, "NetApiBufferFree");
+
+ if (!pNetStatisticsGet || !pNetApiBufferSize || !pNetApiBufferFree)
+ {
+ FreeLibrary (hNetAPI32);
+ hNetAPI32 = NULL;
+ log_debug ("rndw32: No NETAPI found\n" );
+ }
+ }
+
+ /* Initialize the NT kernel native API function pointers if necessary */
+ hNTAPI = GetModuleHandle ("NTDll.dll");
+ if (hNTAPI)
+ {
+ /* Get a pointer to the NT native information query functions */
+ pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)
+ GetProcAddress (hNTAPI, "NtQuerySystemInformation");
+ pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
+ GetProcAddress (hNTAPI, "NtQueryInformationProcess");
+ pNtPowerInformation = (NTPOWERINFORMATION)
+ GetProcAddress(hNTAPI, "NtPowerInformation");
+
+ if (!pNtQuerySystemInformation || !pNtQueryInformationProcess)
+ hNTAPI = NULL;
+ }
+
+
+ is_initialized = 1;
+ }
+
+ read_system_rng ( add, requester );
+ read_mbm_data ( add, requester );
+
+ /* Get network statistics. Note: Both NT Workstation and NT Server by
+ default will be running both the workstation and server services. The
+ heuristic below is probably useful though on the assumption that the
+ majority of the network traffic will be via the appropriate service.
+ In any case the network statistics return almost no randomness. */
+ {
+ LPBYTE lpBuffer;
+
+ if (hNetAPI32
+ && !pNetStatisticsGet (NULL,
+ (LPWSTR)(is_workstation ? L"LanmanWorkstation" :
+ L"LanmanServer"), 0, 0, &lpBuffer))
+ {
+ if ( debug_me )
+ log_debug ("rndw32#slow_gatherer: get netstats\n" );
+ pNetApiBufferSize (lpBuffer, &dwSize);
+ (*add) ( lpBuffer, dwSize, requester );
+ pNetApiBufferFree (lpBuffer);
+ }
+ }
+
+ /* Get disk I/O statistics for all the hard drives. 100 is an
+ arbitrary failsafe limit. */
+ for (drive_no = 0; drive_no < 100 ; drive_no++)
+ {
+ char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8];
+ char szDevice[50];
+
+ /* Check whether we can access this device. */
+ snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d",
+ drive_no);
+ hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hDevice == INVALID_HANDLE_VALUE)
+ break; /* No more drives. */
+
+ /* Note: This only works if you have turned on the disk performance
+ counters with 'diskperf -y'. These counters are off by default. */
+ dwSize = sizeof diskPerformance;
+ if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
+ diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
+ &dwSize, NULL))
+ {
+ if ( debug_me )
+ log_debug ("rndw32#slow_gatherer: iostat drive %d\n",
+ drive_no);
+ (*add) (diskPerformance, dwSize, requester);
+ }
+ else
+ {
+ log_info ("NOTE: you should run 'diskperf -y' "
+ "to enable the disk statistics\n");
+ }
+ CloseHandle (hDevice);
+ }
+
+ /* In theory we should be using the Win32 performance query API to obtain
+ unpredictable data from the system, however this is so unreliable (see
+ the multiple sets of comments in registryPoll()) that it's too risky
+ to rely on it except as a fallback in emergencies. Instead, we rely
+ mostly on the NT native API function NtQuerySystemInformation(), which
+ has the dual advantages that it doesn't have as many (known) problems
+ as the Win32 equivalent and that it doesn't access the data indirectly
+ via pseudo-registry keys, which means that it's much faster. Note
+ that the Win32 equivalent actually works almost all of the time, the
+ problem is that on one or two systems it can fail in strange ways that
+ are never the same and can't be reproduced on any other system, which
+ is why we use the native API here. Microsoft officially documented
+ this function in early 2003, so it'll be fairly safe to use. */
+ if ( !hNTAPI )
+ {
+ registry_poll (add, requester);
+ return;
+ }
+
+
+ /* Scan the first 64 possible information types (we don't bother with
+ increasing the buffer size as we do with the Win32 version of the
+ performance data read, we may miss a few classes but it's no big deal).
+ This scan typically yields around 20 pieces of data, there's nothing
+ in the range 65...128 so chances are there won't be anything above
+ there either. */
+ buffer = xmalloc (PERFORMANCE_BUFFER_SIZE);
+ for (dwType = 0; dwType < 64; dwType++)
+ {
+ switch (dwType)
+ {
+ /* ID 17 = SystemObjectInformation hangs on some win2k systems. */
+ case 17:
+ if (system_is_w2000)
+ continue;
+ break;
+
+ /* Some information types are write-only (the IDs are shared with
+ a set-information call), we skip these. */
+ case 26: case 27: case 38: case 46: case 47: case 48: case 52:
+ continue;
+
+ /* ID 53 = SystemSessionProcessInformation reads input from the
+ output buffer, which has to contain a session ID and pointer
+ to the actual buffer in which to store the session information.
+ Because this isn't a standard query, we skip this. */
+ case 53:
+ continue;
+ }
+
+ /* Query the info for this ID. Some results (for example for
+ ID = 6, SystemCallCounts) are only available in checked builds
+ of the kernel. A smaller subcless of results require that
+ certain system config flags be set, for example
+ SystemObjectInformation requires that the
+ FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags. To avoid
+ having to special-case all of these, we try reading each one and
+ only use those for which we get a success status. */
+ dwResult = pNtQuerySystemInformation (dwType, buffer,
+ PERFORMANCE_BUFFER_SIZE - 2048,
+ &ulSize);
+ if (dwResult != ERROR_SUCCESS)
+ continue;
+
+ /* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24,
+ SystemDpcInformation) incorrectly return a length of zero, so we
+ manually adjust the length to the correct value. */
+ if ( !ulSize )
+ {
+ if (dwType == 23)
+ ulSize = 6 * sizeof (ULONG);
+ else if (dwType == 24)
+ ulSize = 5 * sizeof (ULONG);
+ }
+
+ /* If we got some data back, add it to the entropy pool. */
+ if (ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048)
+ {
+ if (debug_me)
+ log_debug ("rndw32#slow_gatherer: %lu bytes from sysinfo %ld\n",
+ ulSize, dwType);
+ (*add) (buffer, ulSize, requester);
+ no_results++;
+ }
+ }
+
+ /* Now we would do the same for the process information. This
+ call would rather ugly in that it requires an exact length
+ match for the data returned, failing with a
+ STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if the
+ length isn't an exact match. It requires a compiler to handle
+ complex nested structs, alignment issues, and so on, and
+ without the headers in which the entries are declared it's
+ almost impossible to do. Thus we don't. */
+
+
+ /* Finally, do the same for the system power status information. There
+ are only a limited number of useful information types available so we
+ restrict ourselves to the useful types. In addition since this
+ function doesn't return length information, we have to hardcode in
+ length data. */
+ if (pNtPowerInformation)
+ {
+ static const struct { int type; int size; } powerInfo[] = {
+ { 0, 128 }, /* SystemPowerPolicyAc */
+ { 1, 128 }, /* SystemPowerPolicyDc */
+ { 4, 64 }, /* SystemPowerCapabilities */
+ { 5, 48 }, /* SystemBatteryState */
+ { 11, 48 }, /* ProcessorInformation */
+ { 12, 24 }, /* SystemPowerInformation */
+ { -1, -1 }
+ };
+ int i;
+
+ /* The 100 is a failsafe limit. */
+ for (i = 0; powerInfo[i].type != -1 && i < 100; i++ )
+ {
+ /* Query the info for this ID */
+ dwResult = pNtPowerInformation (powerInfo[i].type, NULL, 0, buffer,
+ PERFORMANCE_BUFFER_SIZE - 2048);
+ if (dwResult != ERROR_SUCCESS)
+ continue;
+ if (debug_me)
+ log_debug ("rndw32#slow_gatherer: %u bytes from powerinfo %d\n",
+ powerInfo[i].size, i);
+ (*add) (buffer, powerInfo[i].size, requester);
+ no_results++;
+ }
+ gcry_assert (i < 100);
+ }
+ xfree (buffer);
+
+ /* We couldn't get enough results from the kernel, fall back to the
+ somewhat troublesome registry poll. */
+ if (no_results < 15)
+ registry_poll (add, requester);
+}
+
+
+int
+_gcry_rndw32_gather_random (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level )
+{
+ static int is_initialized;
+ size_t n;
+
+ if (!level)
+ return 0;
+
+ /* We don't differentiate between level 1 and 2 here because there
+ is no internal entropy pool as a scary resource. It may all work
+ slower, but because our entropy source will never block but
+ deliver some not easy to measure entropy, we assume level 2. */
+
+ if (!is_initialized)
+ {
+ OSVERSIONINFO osvi = { sizeof( osvi ) };
+ const char *s;
+
+ if ((s = getenv ("GCRYPT_RNDW32_DBG")) && atoi (s) > 0)
+ debug_me = 1;
+
+ GetVersionEx( &osvi );
+ if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
+ log_fatal ("can only run on a Windows NT platform\n" );
+ system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0);
+
+ init_system_rng ();
+ is_initialized = 1;
+ }
+
+ if (debug_me)
+ log_debug ("rndw32#gather_random: ori=%d len=%u lvl=%d\n",
+ origin, (unsigned int)length, level );
+
+ slow_gatherer (add, origin);
+
+ /* Round requested LENGTH up to full 32 bytes. */
+ n = _gcry_rndjent_poll (add, origin, ((length + 31) / 32) * 32);
+
+ if (debug_me)
+ log_debug ("rndw32#gather_random: jent contributed extra %u bytes\n",
+ (unsigned int)n);
+
+ return 0;
+}
+
+
+
+void
+_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin)
+{
+ static int addedFixedItems = 0;
+
+ if ( debug_me )
+ log_debug ("rndw32#gather_random_fast: ori=%d\n", origin );
+
+ /* Get various basic pieces of system information: Handle of active
+ window, handle of window with mouse capture, handle of clipboard
+ owner handle of start of clpboard viewer list, pseudohandle of
+ current process, current process ID, pseudohandle of current
+ thread, current thread ID, handle of desktop window, handle of
+ window with keyboard focus, whether system queue has any events,
+ cursor position for last message, 1 ms time for last message,
+ handle of window with clipboard open, handle of process heap,
+ handle of procs window station, types of events in input queue,
+ and milliseconds since Windows was started. On 64-bit platform
+ some of these return values are pointers and thus 64-bit wide.
+ We discard the upper 32-bit of those values. */
+
+ {
+ byte buffer[20*sizeof(unsigned long)], *bufptr;
+
+ bufptr = buffer;
+#define ADDINT(f) do { unsigned long along = (unsigned long)(f); \
+ memcpy (bufptr, &along, sizeof (along) ); \
+ bufptr += sizeof (along); \
+ } while (0)
+#define ADDPTR(f) do { void *aptr = (f); \
+ ADDINT((SIZE_T)aptr); \
+ } while (0)
+
+ ADDPTR ( GetActiveWindow ());
+ ADDPTR ( GetCapture ());
+ ADDPTR ( GetClipboardOwner ());
+ ADDPTR ( GetClipboardViewer ());
+ ADDPTR ( GetCurrentProcess ());
+ ADDINT ( GetCurrentProcessId ());
+ ADDPTR ( GetCurrentThread ());
+ ADDINT ( GetCurrentThreadId ());
+ ADDPTR ( GetDesktopWindow ());
+ ADDPTR ( GetFocus ());
+ ADDINT ( GetInputState ());
+ ADDINT ( GetMessagePos ());
+ ADDINT ( GetMessageTime ());
+ ADDPTR ( GetOpenClipboardWindow ());
+ ADDPTR ( GetProcessHeap ());
+ ADDPTR ( GetProcessWindowStation ());
+ /* Following function in some cases stops returning events, and cannot
+ be used as an entropy source. */
+ /*ADDINT ( GetQueueStatus (QS_ALLEVENTS));*/
+ ADDINT ( GetTickCount ());
+
+ gcry_assert ( bufptr-buffer < sizeof (buffer) );
+ (*add) ( buffer, bufptr-buffer, origin );
+#undef ADDINT
+#undef ADDPTR
+ }
+
+ /* Get multiword system information: Current caret position, current
+ mouse cursor position. */
+ {
+ POINT point;
+
+ GetCaretPos (&point);
+ (*add) ( &point, sizeof (point), origin );
+ GetCursorPos (&point);
+ (*add) ( &point, sizeof (point), origin );
+ }
+
+ /* Get percent of memory in use, bytes of physical memory, bytes of
+ free physical memory, bytes in paging file, free bytes in paging
+ file, user bytes of address space, and free user bytes. */
+ {
+ MEMORYSTATUS memoryStatus;
+
+ memoryStatus.dwLength = sizeof (MEMORYSTATUS);
+ GlobalMemoryStatus (&memoryStatus);
+ (*add) ( &memoryStatus, sizeof (memoryStatus), origin );
+ }
+
+ /* Get thread and process creation time, exit time, time in kernel
+ mode, and time in user mode in 100ns intervals. */
+ {
+ HANDLE handle;
+ FILETIME creationTime, exitTime, kernelTime, userTime;
+ SIZE_T minimumWorkingSetSize, maximumWorkingSetSize;
+
+ handle = GetCurrentThread ();
+ GetThreadTimes (handle, &creationTime, &exitTime,
+ &kernelTime, &userTime);
+ (*add) ( &creationTime, sizeof (creationTime), origin );
+ (*add) ( &exitTime, sizeof (exitTime), origin );
+ (*add) ( &kernelTime, sizeof (kernelTime), origin );
+ (*add) ( &userTime, sizeof (userTime), origin );
+
+ handle = GetCurrentProcess ();
+ GetProcessTimes (handle, &creationTime, &exitTime,
+ &kernelTime, &userTime);
+ (*add) ( &creationTime, sizeof (creationTime), origin );
+ (*add) ( &exitTime, sizeof (exitTime), origin );
+ (*add) ( &kernelTime, sizeof (kernelTime), origin );
+ (*add) ( &userTime, sizeof (userTime), origin );
+
+ /* Get the minimum and maximum working set size for the current
+ process. */
+ GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
+ &maximumWorkingSetSize);
+ /* On 64-bit system, discard the high 32-bits. */
+ (*add) ( &minimumWorkingSetSize, sizeof (int), origin );
+ (*add) ( &maximumWorkingSetSize, sizeof (int), origin );
+ }
+
+
+ /* The following are fixed for the lifetime of the process so we only
+ * add them once */
+ if (!addedFixedItems)
+ {
+ STARTUPINFO startupInfo;
+
+ /* Get name of desktop, console window title, new window
+ position and size, window flags, and handles for stdin,
+ stdout, and stderr. */
+ startupInfo.cb = sizeof (STARTUPINFO);
+ GetStartupInfo (&startupInfo);
+ (*add) ( &startupInfo, sizeof (STARTUPINFO), origin );
+ addedFixedItems = 1;
+ }
+
+ /* The performance of QPC varies depending on the architecture it's
+ running on and on the OS, the MS documentation is vague about the
+ details because it varies so much. Under Win9x/ME it reads the
+ 1.193180 MHz PIC timer. Under NT/Win2K/XP it may or may not read the
+ 64-bit TSC depending on the HAL and assorted other circumstances,
+ generally on machines with a uniprocessor HAL
+ KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines
+ with a multiprocessor or APIC HAL it uses the TSC (the exact time
+ source is controlled by the HalpUse8254 flag in the kernel). That
+ choice of time sources is somewhat peculiar because on a
+ multiprocessor machine it's theoretically possible to get completely
+ different TSC readings depending on which CPU you're currently
+ running on, while for uniprocessor machines it's not a problem.
+ However, the kernel appears to synchronise the TSCs across CPUs at
+ boot time (it resets the TSC as part of its system init), so this
+ shouldn't really be a problem. Under WinCE it's completely platform-
+ dependent, if there's no hardware performance counter available, it
+ uses the 1ms system timer.
+
+ Another feature of the TSC (although it doesn't really affect us here)
+ is that mobile CPUs will turn off the TSC when they idle, Pentiums
+ will change the rate of the counter when they clock-throttle (to
+ match the current CPU speed), and hyperthreading Pentiums will turn
+ it off when both threads are idle (this more or less makes sense,
+ since the CPU will be in the halted state and not executing any
+ instructions to count).
+
+ To make things unambiguous, we detect a CPU new enough to call RDTSC
+ directly by checking for CPUID capabilities, and fall back to QPC if
+ this isn't present.
+
+ On AMD64, TSC is always available and intrinsic is provided for accessing
+ it. */
+#ifdef __x86_64__
+ {
+ unsigned __int64 aint64;
+
+ /* Note: cryptlib does not discard upper 32 bits of TSC on WIN64, but does
+ * on WIN32. Is this correct? */
+ aint64 = __rdtsc();
+ (*add) (&aint64, sizeof(aint64), origin);
+ }
+#else
+#ifdef __GNUC__
+/* FIXME: We would need to implement the CPU feature tests first. */
+/* if (cpu_has_feature_rdtsc) */
+/* { */
+/* uint32_t lo, hi; */
+ /* We cannot use "=A", since this would use %rax on x86_64. */
+/* __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */
+ /* Ignore high 32 bits, hwich are >1s res. */
+/* (*add) (&lo, 4, origin ); */
+/* } */
+/* else */
+#endif /*!__GNUC__*/
+ {
+ LARGE_INTEGER performanceCount;
+
+ if (QueryPerformanceCounter (&performanceCount))
+ {
+ if ( debug_me )
+ log_debug ("rndw32#gather_random_fast: perf data\n");
+ (*add) (&performanceCount, sizeof (performanceCount), origin);
+ }
+ else
+ {
+ /* Millisecond accuracy at best... */
+ DWORD aword = GetTickCount ();
+ (*add) (&aword, sizeof (aword), origin );
+ }
+ }
+#endif /*__x86_64__*/
+
+
+}
diff --git a/comm/third_party/libgcrypt/random/rndw32ce.c b/comm/third_party/libgcrypt/random/rndw32ce.c
new file mode 100644
index 0000000000..873e84606a
--- /dev/null
+++ b/comm/third_party/libgcrypt/random/rndw32ce.c
@@ -0,0 +1,199 @@
+/* rndw32ce.c - W32CE entropy gatherer
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+
+/* The Microsoft docs say that it is suggested to see the buffer with
+ some extra random. We do this, despite that it is a questionable
+ suggestion as the OS as better means of collecting entropy than an
+ application. */
+static size_t filler_used;
+static size_t filler_length;
+static unsigned char *filler_buffer;
+
+static void
+filler (const void *data, size_t datalen, enum random_origins dummy)
+{
+ (void)dummy;
+ if (filler_used + datalen > filler_length)
+ datalen = filler_length - filler_used;
+ memcpy (filler_buffer + filler_used, data, datalen);
+ filler_used += datalen;
+}
+
+
+static void
+fillup_buffer (unsigned char *buffer, size_t length)
+{
+ filler_used = 0;
+ filler_length = length;
+ filler_buffer = buffer;
+
+ while (filler_used < length)
+ _gcry_rndw32ce_gather_random_fast (filler, 0);
+}
+
+
+int
+_gcry_rndw32ce_gather_random (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin,
+ size_t length, int level )
+{
+ HCRYPTPROV prov;
+ unsigned char buffer [256];
+ DWORD buflen;
+
+ if (!level)
+ return 0;
+
+ /* Note that LENGTH is not really important because the caller
+ checks the returned lengths and calls this function until it
+ feels that enough entropy has been gathered. */
+
+ buflen = sizeof buffer;
+ if (length+8 < buflen)
+ buflen = length+8; /* Return a bit more than requested. */
+
+ if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,
+ (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
+ log_debug ("CryptAcquireContext failed: rc=%d\n", (int)GetLastError ());
+ else
+ {
+ fillup_buffer (buffer, buflen);
+ if (!CryptGenRandom (prov, buflen, buffer))
+ log_debug ("CryptGenRandom(%d) failed: rc=%d\n",
+ (int)buflen, (int)GetLastError ());
+ else
+ (*add) (buffer, buflen, origin);
+ CryptReleaseContext (prov, 0);
+ wipememory (buffer, sizeof buffer);
+ }
+
+ return 0;
+}
+
+
+
+void
+_gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
+ enum random_origins),
+ enum random_origins origin)
+{
+
+ /* Add word sized values. */
+ {
+# define ADD(t,f) do { \
+ t along = (f); \
+ memcpy (bufptr, &along, sizeof (along)); \
+ bufptr += sizeof (along); \
+ } while (0)
+ unsigned char buffer[20*sizeof(unsigned long)], *bufptr;
+
+ bufptr = buffer;
+ ADD (HWND, GetActiveWindow ());
+ ADD (HWND, GetCapture ());
+ ADD (HWND, GetClipboardOwner ());
+ ADD (HANDLE, GetCurrentProcess ());
+ ADD (DWORD, GetCurrentProcessId ());
+ ADD (HANDLE, GetCurrentThread ());
+ ADD (DWORD, GetCurrentThreadId ());
+ ADD (HWND, GetDesktopWindow ());
+ ADD (HWND, GetFocus ());
+ ADD (DWORD, GetMessagePos ());
+ ADD (HWND, GetOpenClipboardWindow ());
+ ADD (HWND, GetProcessHeap ());
+ ADD (DWORD, GetQueueStatus (QS_ALLEVENTS));
+ ADD (DWORD, GetTickCount ());
+
+ gcry_assert ( bufptr-buffer < sizeof (buffer) );
+ (*add) ( buffer, bufptr-buffer, origin );
+# undef ADD
+ }
+
+ /* Get multiword system information: Current caret position, current
+ mouse cursor position. */
+ {
+ POINT point;
+
+ GetCaretPos (&point);
+ (*add) ( &point, sizeof (point), origin );
+ GetCursorPos (&point);
+ (*add) ( &point, sizeof (point), origin );
+ }
+
+ /* Get percent of memory in use, bytes of physical memory, bytes of
+ free physical memory, bytes in paging file, free bytes in paging
+ file, user bytes of address space, and free user bytes. */
+ {
+ MEMORYSTATUS memoryStatus;
+
+ memoryStatus.dwLength = sizeof (MEMORYSTATUS);
+ GlobalMemoryStatus (&memoryStatus);
+ (*add) ( &memoryStatus, sizeof (memoryStatus), origin );
+ }
+
+
+ /* Get thread and process creation time, exit time, time in kernel
+ mode, and time in user mode in 100ns intervals. */
+ {
+ HANDLE handle;
+ FILETIME creationTime, exitTime, kernelTime, userTime;
+
+ handle = GetCurrentThread ();
+ GetThreadTimes (handle, &creationTime, &exitTime,
+ &kernelTime, &userTime);
+ (*add) ( &creationTime, sizeof (creationTime), origin );
+ (*add) ( &exitTime, sizeof (exitTime), origin );
+ (*add) ( &kernelTime, sizeof (kernelTime), origin );
+ (*add) ( &userTime, sizeof (userTime), origin );
+
+ handle = GetCurrentThread ();
+ GetThreadTimes (handle, &creationTime, &exitTime,
+ &kernelTime, &userTime);
+ (*add) ( &creationTime, sizeof (creationTime), origin );
+ (*add) ( &exitTime, sizeof (exitTime), origin );
+ (*add) ( &kernelTime, sizeof (kernelTime), origin );
+ (*add) ( &userTime, sizeof (userTime), origin );
+
+ }
+
+
+ /* In case the OEM provides a high precision timer get this. If
+ none is available the default implementation returns the
+ GetTickCount. */
+ {
+ LARGE_INTEGER performanceCount;
+
+ if (QueryPerformanceCounter (&performanceCount))
+ (*add) (&performanceCount, sizeof (performanceCount), origin);
+ }
+
+}