diff --git a/.github/workflows/actions-ci.yml b/.github/workflows/actions-ci.yml index 311d54b17a..42fd481119 100644 --- a/.github/workflows/actions-ci.yml +++ b/.github/workflows/actions-ci.yml @@ -84,6 +84,9 @@ jobs: - uses: actions/setup-go@v4 with: go-version: '>=1.18' + - name: Runner information + run: | + sysctl -a | grep machdep.cpu - name: Build ${{ env.PACKAGE_NAME }} run: | ./tests/ci/run_posix_tests.sh @@ -103,7 +106,10 @@ jobs: - uses: actions/setup-go@v4 with: go-version: '>=1.18' - - name: Build ${{ env.PACKAGE_NAME }} with FIPS mode + - name: Runner information + run: | + sysctl -a | grep machdep.cpu + - name: Build ${{ env.PACKAGE_NAME }} run: | ./tests/ci/run_fips_tests.sh diff --git a/crypto/fipsmodule/rand/cpu_jitter_test.cc b/crypto/fipsmodule/rand/cpu_jitter_test.cc index a1872f52f0..b70afec783 100644 --- a/crypto/fipsmodule/rand/cpu_jitter_test.cc +++ b/crypto/fipsmodule/rand/cpu_jitter_test.cc @@ -61,7 +61,7 @@ TEST(CPUJitterEntropyTest, Basic) { EXPECT_EQ(jent_read_entropy_safe(&jitter_ec.instance, (char*) data1, data_len), data_len); - // Verify that the Jitter library version is v3.4.0. - unsigned int jitter_version = 3040000; + // Verify that the Jitter library version is v3.6.0. + unsigned int jitter_version = 3060000; EXPECT_EQ(jitter_version, jent_version()); } diff --git a/third_party/jitterentropy/CHANGES.md b/third_party/jitterentropy/CHANGES.md new file mode 100644 index 0000000000..d9efbd131e --- /dev/null +++ b/third_party/jitterentropy/CHANGES.md @@ -0,0 +1,125 @@ +3.6.0 + * Remove bi-modal behavior of conditioning function + * Make jent_read_entropy_safe safer by retrying the health test + * Move the version information to make them available at compile time + +3.5.0 + * add distinction between intermittent and permanent health failure + + * add compile time option to allow configuring a mask to reduce the size of + the time stamp used for the APT + +3.4.1 + * add FIPS 140 hints to man page + * simplify the test tool to search for optimal configurations + * fix: jent_loop_shuffle: re-add setting the time that was lost with 3.4.0 + * enhancement: add ARM64 assembler code to read high-res timer + +3.4.0 + * enhancement: add API call jent_set_fips_failure_callback as requested by Daniel Ojalvo + * fix: Change the SHA-3 integration: The entropy pool is now a SHA-3 state. +It is filled with the time delta containing entropy and auxiliary data that does not contain entropy using a SHA update operation. The auxiliary data is calculated by a SHA-3 hashing of some varying state data. The time delta that contains entropy is measured about the SHA-3 hasing of the auxiliary data. This satisfies FIPS 140-3 IG D.K resolutions 4, 6, and 8. + * enhancement: add CMake support by Andrew Hopkins + +3.3.1 + * fix: bug fix in initialization logic by Vladis Dronov + * fix: use __asm__ instead of asm to suit the C11 standard + +3.3.0 + * add jent_get_cachesize if _SC_LEVEL1_DCACHE_SIZE is not defined + * limit the memory buffer size allocated and allow caller to provide + the means to provide a limit, too + * fix: update man page + * update README explaining how to handle entropy shortfall to make it consistent with the current code base + +3.2.0 + * fix: add API call jent_read_entropy_safe to header file + * enhancement: add jent_entropy_init_ex API call + * enhancement: call jent_entropy_init_ex automatically when jent_entropy_collector_alloc_internal detects that no self test has yet been performed + * test: provide jitterentropy-rng test tool allowing all options exported by the library to be invoked + * fix: re-add check of time_backwards in power-on test + * fix: silence static code analysis tool + * test: add test for GCD + * enhancement: add GCD selftest + * fix: simplify memory management for SHA-3 + * enhancement: add random memory access (JENT_RANDOM_MEMACCESS) + +3.1.0 + * Add link call to pthreads library as suggested by Mikhail Novosyolov + * Add ENTROPY_SAFETY_FACTOR to apply consideration of asymptotically reaching + full entropy following SP800-90C suggested by Joshua Hill + * Add test for finiding more entropy by changing the memory buffer size + used for the memory access loop + * Increase the memory buffer size to 512 kBytes per default based on + measurements on systems with low entropy. + * Add jent_ncpu() detecting the number of existing CPUs. Only when more than + one CPU is in the system, the internal timer thread is started. + * add GCD testing and analysis suggested by Joshua Hill + * add fixes to APT suggested by Joshua Hill + * add lag predictor health test suggested by Joshua Hill + * add jent_read_entropy_safe API call + * break up jitterentropy-base.c into various smaller code files + +3.0.2 + * Small fixes suggested by Joshua Hill + * Update the invocation of SHA-3 invocation: each loop iteration defined by the loop shuffle is a self-contained SHA-3 operation. Therefore, the conditioning information is always *one* SHA-3 operation with different time duration. + * add JENT_CONF_DISABLE_LOOP_SHUFFLE config option allowing disabling of the shuffle operation + * Use -O0 + +3.0.1 + * on older GCC versions use -fstack-protector as suggested by Warszawski, + Diego + * prevent creating the internal timer thread if a high-res hardware timer is + found as reported by Lonnie Abelbeck + +3.0.0 + * use RDTSC on x86 directly instead of clock_gettime + * use SHA-3 instead of LFSR + * add internal high-resolution timer support + +2.2.0 + * SP800-90B compliance: Add RCT runtime health test + * SP800-90B compliance: Add Chi-Squared runtime health test as a replacement + for the adaptive proportion test + * SP800-90B compliance: Increase initial entropy test to 1024 rounds + * SP800-90B compliance: Invoke runtime health tests during initialization + * remove FIPS 140-2 continuous self test (RCT covers the requirement as per + FIPS 140-2 IG 9.8) + * SP800-90B compliance: Do not mix stuck time deltas into entropy pool + +2.1.2: + * Add static library compilation thanks to Neil Horman + * Initialize variable ec to satisfy valgrind as suggested by Steve Grubb + * Add cross-compilation support suggested by Lonnie Abelbeck + +2.1.1: + * Fix implementation of mathematical properties. + +2.1.0: + * Convert all __[u|s][32|64] into [uint|int][32|64]_t + * Remove all code protected by #if defined(__KERNEL__) && !defined(MODULE) + * Add JENT_PRIVATE_COMPILE: Enable flag during compile when + compiling a private copy of the Jitter RNG + * Remove unused statistical test code + * Add FIPS 140-2 continuous self test code + * threshold for init-time stuck test configurable with JENT_STUCK_INIT_THRES + during compile time + +2.0.1: + * Invcation of stuck test during initalization + +2.0.0: + * Replace the XOR folding of a time delta with an LFSR -- the use of an + LFSR is mathematically more sound for the argument to maintain entropy + +1.2.0: + * Use constant time operation of jent_stir_pool to prevent leaking + timing information about RNG. + * Make it compile on 32 bit archtectures + +1.1.0: + * start new numbering schema + * update processing of bit that is deemed holding no entropy by heuristic: + XOR it into pool without LSFR and bit rotation (reported and suggested + by Kevin Fowler ) + diff --git a/third_party/jitterentropy/CMakeLists.txt b/third_party/jitterentropy/CMakeLists.txt index 3b107addcf..ceef308699 100644 --- a/third_party/jitterentropy/CMakeLists.txt +++ b/third_party/jitterentropy/CMakeLists.txt @@ -7,14 +7,15 @@ # the same as the source code. set(JITTER_SOURCES - ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/jitterentropy-base.c - ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/jitterentropy-gcd.c - ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/jitterentropy-health.c - ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/jitterentropy-noise.c - ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/jitterentropy-sha3.c - ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/jitterentropy-timer.c) + ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/src/jitterentropy-base.c + ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/src/jitterentropy-gcd.c + ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/src/jitterentropy-health.c + ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/src/jitterentropy-noise.c + ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/src/jitterentropy-sha3.c + ${PROJECT_SOURCE_DIR}/third_party/jitterentropy/src/jitterentropy-timer.c) include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/third_party/jitterentropy) if(WIN32) if(MSVC) @@ -32,6 +33,10 @@ else() # https://gcc.gnu.org/wiki/NewWconversion. set(JITTER_COMPILE_FLAGS "${JITTER_COMPILE_FLAGS} -Wconversion") endif() + + if(BORINGSSL_PREFIX) + set(JITTER_COMPILE_FLAGS "${JITTER_COMPILE_FLAGS} --include=${PROJECT_BINARY_DIR}/symbol_prefix_include/openssl/boringssl_prefix_symbols.h") + endif() endif() set_source_files_properties(${JITTER_SOURCES} PROPERTIES COMPILE_FLAGS "${JITTER_COMPILE_FLAGS}") diff --git a/third_party/jitterentropy/LICENSE b/third_party/jitterentropy/LICENSE index cc9d1f1848..dd266c1fc6 100644 --- a/third_party/jitterentropy/LICENSE +++ b/third_party/jitterentropy/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2017 - 2022, Stephan Mueller +Copyright (C) 2017 - 2024, Stephan Mueller Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/third_party/jitterentropy/Makefile b/third_party/jitterentropy/Makefile new file mode 100644 index 0000000000..b871ead9d7 --- /dev/null +++ b/third_party/jitterentropy/Makefile @@ -0,0 +1,113 @@ +# Compile Noise Source as user space application + +CC ?= gcc +#Hardening +ENABLE_STACK_PROTECTOR ?= 1 +CFLAGS ?= -fwrapv --param ssp-buffer-size=4 -fvisibility=hidden -fPIE -Wcast-align -Wmissing-field-initializers -Wshadow -Wswitch-enum +CFLAGS +=-Wextra -Wall -pedantic -fPIC -O0 -fwrapv -Wconversion +LDFLAGS +=-Wl,-z,relro,-z,now -lpthread + +# Enable internal timer support +CFLAGS += -DJENT_CONF_ENABLE_INTERNAL_TIMER + +GCCVERSIONFORMAT := $(shell echo `$(CC) -dumpversion | sed 's/\./\n/g' | wc -l`) +ifeq "$(GCCVERSIONFORMAT)" "3" + GCC_GTEQ_490 := $(shell expr `$(CC) -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40900) +else + GCC_GTEQ_490 := $(shell expr `$(CC) -dumpfullversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40900) +endif + +ifeq "$(ENABLE_STACK_PROTECTOR)" "1" + ifeq "$(GCC_GTEQ_490)" "1" + CFLAGS += -fstack-protector-strong + else + CFLAGS += -fstack-protector-all + endif +endif + +# Change as necessary +PREFIX := /usr/local +# library target directory (either lib or lib64) +LIBDIR := lib + +# include target directory +INCDIR := include +SRCDIR := src + +INSTALL_STRIP ?= install -s + +NAME := jitterentropy +LIBMAJOR=$(shell cat jitterentropy.h | egrep "define\s+JENT_MAJVERSION" | awk '{print $$3}') +LIBMINOR=$(shell cat jitterentropy.h | egrep "define\s+JENT_MINVERSION" | awk '{print $$3}') +LIBPATCH=$(shell cat jitterentropy.h | egrep "define\s+JENT_PATCHLEVEL" | awk '{print $$3}') +LIBVERSION := $(LIBMAJOR).$(LIBMINOR).$(LIBPATCH) + +VPATH := $(SRCDIR) +C_SRCS := $(notdir $(sort $(wildcard $(SRCDIR)/*.c))) +C_OBJS := ${C_SRCS:.c=.o} +OBJS := $(C_OBJS) + +analyze_srcs = $(filter %.c, $(sort $(C_SRCS))) +analyze_plists = $(analyze_srcs:%.c=%.plist) + +INCLUDE_DIRS := . $(SRCDIR) +LIBRARY_DIRS := +LIBRARIES := rt + +CFLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(LIBRARIES),-l$(library)) + +.PHONY: all scan install clean distclean check $(NAME) $(NAME)-static + +all: $(NAME) $(NAME)-static + +lib$(NAME).a: $(OBJS) + $(AR) rcs lib$(NAME).a $(OBJS) + +lib$(NAME).so.$(LIBVERSION): $(OBJS) + $(CC) -shared -Wl,-soname,lib$(NAME).so.$(LIBMAJOR) -o lib$(NAME).so.$(LIBVERSION) $(OBJS) $(LDFLAGS) + +$(NAME)-static: lib$(NAME).a +$(NAME): lib$(NAME).so.$(LIBVERSION) + +$(analyze_plists): %.plist: %.c + @echo " CCSA " $@ + clang --analyze $(CFLAGS) $< -o $@ + +scan: $(analyze_plists) + +cppcheck: + cppcheck --force -q --enable=performance --enable=warning --enable=portability $(shell find * -name \*.h -o -name \*.c) + +install: install-man install-shared install-includes + +install-man: + install -d -m 0755 $(DESTDIR)$(PREFIX)/share/man/man3 + install -m 644 doc/$(NAME).3 $(DESTDIR)$(PREFIX)/share/man/man3/ + gzip -n -f -9 $(DESTDIR)$(PREFIX)/share/man/man3/$(NAME).3 + +install-shared: + install -d -m 0755 $(DESTDIR)$(PREFIX)/$(LIBDIR) + $(INSTALL_STRIP) -m 0755 lib$(NAME).so.$(LIBVERSION) $(DESTDIR)$(PREFIX)/$(LIBDIR)/ + $(RM) $(DESTDIR)$(PREFIX)/$(LIBDIR)/lib$(NAME).so.$(LIBMAJOR) + ln -sf lib$(NAME).so.$(LIBVERSION) $(DESTDIR)$(PREFIX)/$(LIBDIR)/lib$(NAME).so.$(LIBMAJOR) + ln -sf lib$(NAME).so.$(LIBMAJOR) $(DESTDIR)$(PREFIX)/$(LIBDIR)/lib$(NAME).so + +install-includes: + install -d -m 0755 $(DESTDIR)$(PREFIX)/$(INCDIR) + install -m 0644 jitterentropy.h $(DESTDIR)$(PREFIX)/$(INCDIR)/ + install -m 0644 jitterentropy-base-user.h $(DESTDIR)$(PREFIX)/$(INCDIR)/ + +install-static: + install -d -m 0755 $(DESTDIR)$(PREFIX)/$(LIBDIR) + install -m 0755 lib$(NAME).a $(DESTDIR)$(PREFIX)/$(LIBDIR)/ + +clean: + @- $(RM) $(NAME) + @- $(RM) $(OBJS) + @- $(RM) lib$(NAME).so* + @- $(RM) lib$(NAME).a + @- $(RM) $(analyze_plists) + +distclean: clean diff --git a/third_party/jitterentropy/README.md b/third_party/jitterentropy/README.md index 90fc25d4cc..73a1961f8b 100644 --- a/third_party/jitterentropy/README.md +++ b/third_party/jitterentropy/README.md @@ -1,16 +1,3 @@ -NOTE -======================================= - -The source code in this directory is taken from CPU Jitter RNG library -version v3.4.0, available at: -https://github.com/smuellerDD/jitterentropy-library. - -The following changes were made to the original source code to integrate -the library with AWS-LC: -* `asm volatile` was changed to `__asm__volatile` - -The original README.md file starts below. - Hardware RNG based on CPU timing jitter ======================================= @@ -23,7 +10,7 @@ The implementation of the Jitter RNG is independent of any operating system. As such, it could even run on baremetal without any operating system. The design of the RNG is given in the documentation found in at -http://www.chronox.de/jent.html . This documentation also covers the full +http://www.chronox.de/jent . This documentation also covers the full assessment of the SP800-90B compliance as well as all required test code. API diff --git a/third_party/jitterentropy/arch/android/Android.mk b/third_party/jitterentropy/arch/android/Android.mk new file mode 100644 index 0000000000..0f2f9b83b7 --- /dev/null +++ b/third_party/jitterentropy/arch/android/Android.mk @@ -0,0 +1,34 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := jitterentropy +LOCAL_CFLAGS := -O0 -DCRYPTO_CPU_JITTERENTROPY_STAT +LOCAL_SRC_FILES := jitterentropy-base.c jitterentropy-stat.c jitterentropy-foldtime.c + +# compile into a shared library that can be pulled into an APK +LOCAL_STATIC_LIBRARIES := android_native_app_glue +include $(BUILD_SHARED_LIBRARY) +$(call import-module,android/native_app_glue) + +# compilation of a standalone-binary that must be manually moved to +# Android /data partition for execution. +#include $(BUILD_EXECUTABLE) + +# compilation of the CPU Jitter RNG app +#LOCAL_SRC_FILES := jitterentropy-base.c jitterentropy-main-user.c + diff --git a/third_party/jitterentropy/arch/android/AndroidManifest.xml b/third_party/jitterentropy/arch/android/AndroidManifest.xml new file mode 100644 index 0000000000..53ef746148 --- /dev/null +++ b/third_party/jitterentropy/arch/android/AndroidManifest.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/third_party/jitterentropy/arch/android/README b/third_party/jitterentropy/arch/android/README new file mode 100644 index 0000000000..75c327635c --- /dev/null +++ b/third_party/jitterentropy/arch/android/README @@ -0,0 +1,14 @@ +See comments in Android.mk + +When compiling an APK, follow roughly these steps + +1. create dir /jitterentropy +2. copy AndroidManifest.xml to /jitterentropy +3. copy code and Android.mk to /jitterentropy/jni +4. cd /jitterentropy +5. open eclipse and import project +6. on console android update project -p . -s +7. ../ndk-build +8. in eclipse: open manifest and compile + +am start -n de.chronox.jitterentropy/android.app.NativeActivity diff --git a/third_party/jitterentropy/arch/jitterentropy-base-power.h b/third_party/jitterentropy/arch/jitterentropy-base-power.h new file mode 100644 index 0000000000..2cb35ad2e1 --- /dev/null +++ b/third_party/jitterentropy/arch/jitterentropy-base-power.h @@ -0,0 +1,147 @@ +/* + * Non-physical true random number generator based on timing jitter. + * + * Copyright Stephan Mueller , 2013 - 2024 + * + * 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_BASE_POWER_H +#define _JITTERENTROPY_BASE_POWER_H + +#include +#include +#include +#include + +/* taken from http://www.ecrypt.eu.org/ebats/cpucycles.html */ + +static inline void jent_get_nstime(uint64_t *out) +{ + unsigned long high; + unsigned long low; + unsigned long newhigh; + uint64_t result; + __asm__ __volatile__( + "Lcpucycles:mftbu %0;mftb %1;mftbu %2;cmpw %0,%2;bne Lcpucycles" + : "=r" (high), "=r" (low), "=r" (newhigh) + ); + result = high; + result <<= 32; + result |= low; + *out = result; +} + +static inline void *jent_zalloc(size_t len) +{ + void *tmp = NULL; + /* we have no secure memory allocation! Hence + * we do not sed CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY */ + tmp = malloc(len); + if(NULL != tmp) + memset(tmp, 0, len); + return tmp; +} + +static inline void jent_zfree(void *ptr, unsigned int len) +{ + memset(ptr, 0, len); + free(ptr); +} + +static inline int jent_fips_enabled(void) +{ + return 0; +} + +static inline long jent_ncpu(void) +{ + /* + * TODO: return number of available CPUs - + * this code disables timer thread as only one CPU is "detected". + */ + return 1; +} + +static inline void jent_yield(void) +{ + sched_yield(); +} + +static inline uint32_t jent_cache_size_roundup(void) +{ +#ifdef __linux__ + long l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE); + long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE); + long l3 = sysconf(_SC_LEVEL3_CACHE_SIZE); + uint32_t cache_size = 0; + + /* Cache size reported by system */ + if (l1 > 0) + cache_size += (uint32_t)l1; + if (l2 > 0) + cache_size += (uint32_t)l2; + if (l3 > 0) + cache_size += (uint32_t)l3; + + /* Force the output_size to be of the form (bounding_power_of_2 - 1). */ + cache_size |= (cache_size >> 1); + cache_size |= (cache_size >> 2); + cache_size |= (cache_size >> 4); + cache_size |= (cache_size >> 8); + cache_size |= (cache_size >> 16); + + if (cache_size == 0) + return 0; + + /* Make the output_size the smallest power of 2 strictly greater than cache_size. */ + cache_size++; + + return cache_size; +#else + return 0; +#endif +} + +/* --- helpers needed in user space -- */ + +static inline uint64_t rol64(uint64_t x, int n) +{ + return ( (x << (n&(64-1))) | (x >> ((64-n)&(64-1))) ); +} + +#endif /* _JITTERENTROPY_BASE_POWER_H */ + diff --git a/third_party/jitterentropy/arch/jitterentropy-base-s390.h b/third_party/jitterentropy/arch/jitterentropy-base-s390.h new file mode 100644 index 0000000000..479441a4c1 --- /dev/null +++ b/third_party/jitterentropy/arch/jitterentropy-base-s390.h @@ -0,0 +1,140 @@ +/* + * Non-physical true random number generator based on timing jitter. + * + * Copyright Stephan Mueller , 2013 - 2024 + * + * 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_BASE_S390_H +#define _JITTERENTROPY_BASE_S390_H + +#include +#include +#include +#include + +static inline void jent_get_nstime(uint64_t *out) +{ + uint64_t clk; + /* this is MVS code! enable with -S in the compiler */ + /*__asm__ volatile("stck %0" : "=m" (clk) : : "cc"); */ + /* this is gcc */ + __asm__ __volatile__("stcke %0" : "=Q" (clk) : : "cc"); + *out = (uint64_t)(clk); +} + +static inline void *jent_zalloc(size_t len) +{ + void *tmp = NULL; + /* we have no secure memory allocation! Hence + * we do not sed CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY */ + tmp = malloc(len); + if(NULL != tmp) + memset(tmp, 0, len); + return tmp; +} + +static inline void jent_zfree(void *ptr, unsigned int len) +{ + memset(ptr, 0, len); + free(ptr); +} + +static inline int jent_fips_enabled(void) +{ + return 0; +} + +static inline long jent_ncpu(void) +{ + /* + * TODO: return number of available CPUs - + * this code disables timer thread as only one CPU is "detected". + */ + return 1; +} + +static inline void jent_yield(void) +{ + sched_yield(); +} + +static inline uint32_t jent_cache_size_roundup(void) +{ +#ifdef __linux__ + long l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE); + long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE); + long l3 = sysconf(_SC_LEVEL3_CACHE_SIZE); + uint32_t cache_size = 0; + + /* Cache size reported by system */ + if (l1 > 0) + cache_size += (uint32_t)l1; + if (l2 > 0) + cache_size += (uint32_t)l2; + if (l3 > 0) + cache_size += (uint32_t)l3; + + /* Force the output_size to be of the form (bounding_power_of_2 - 1). */ + cache_size |= (cache_size >> 1); + cache_size |= (cache_size >> 2); + cache_size |= (cache_size >> 4); + cache_size |= (cache_size >> 8); + cache_size |= (cache_size >> 16); + + if (cache_size == 0) + return 0; + + /* Make the output_size the smallest power of 2 strictly greater than cache_size. */ + cache_size++; + + return cache_size; +#else + return 0; +#endif +} + +/* --- helpers needed in user space -- */ + +static inline uint64_t rol64(uint64_t x, int n) +{ + return ( (x << (n&(64-1))) | (x >> ((64-n)&(64-1))) ); +} + + +#endif /* _JITTERENTROPY_BASE_S390_H */ + diff --git a/third_party/jitterentropy/arch/jitterentropy-base-windows.h b/third_party/jitterentropy/arch/jitterentropy-base-windows.h index b5fed7c291..f9523247fd 100644 --- a/third_party/jitterentropy/arch/jitterentropy-base-windows.h +++ b/third_party/jitterentropy/arch/jitterentropy-base-windows.h @@ -1,7 +1,7 @@ /* * Non-physical true random number generator based on timing jitter. * - * Copyright Stephan Mueller , 2013 - 2022 + * Copyright Stephan Mueller , 2013 - 2024 * * License * ======= @@ -66,14 +66,14 @@ static inline void jent_get_nstime(uint64_t *out) { #if defined(_M_ARM) || defined(_M_ARM64) - // Generic code. + /* Generic code. */ LARGE_INTEGER ticks; QueryPerformanceCounter(&ticks); *out = ticks.QuadPart; #else - // x86, x86_64 intrinsic + /* x86, x86_64 intrinsic */ *out = __rdtsc(); #endif diff --git a/third_party/jitterentropy/arch/jitterentropy-base-x86.h b/third_party/jitterentropy/arch/jitterentropy-base-x86.h index c133ca1db0..e3b8f0bf8d 100644 --- a/third_party/jitterentropy/arch/jitterentropy-base-x86.h +++ b/third_party/jitterentropy/arch/jitterentropy-base-x86.h @@ -1,7 +1,7 @@ /* * Non-physical true random number generator based on timing jitter. * - * Copyright Stephan Mueller , 2013 - 2022 + * Copyright Stephan Mueller , 2013 - 2024 * * License * ======= diff --git a/third_party/jitterentropy/doc/README b/third_party/jitterentropy/doc/README new file mode 100644 index 0000000000..0fbcf69ce3 --- /dev/null +++ b/third_party/jitterentropy/doc/README @@ -0,0 +1 @@ +For design documentation, see http://www.chronox.de diff --git a/third_party/jitterentropy/doc/jitterentropy.3 b/third_party/jitterentropy/doc/jitterentropy.3 new file mode 100644 index 0000000000..5c71201053 --- /dev/null +++ b/third_party/jitterentropy/doc/jitterentropy.3 @@ -0,0 +1,342 @@ +.\" Copyright (c) 2013 - 2024 by Stephan Mueller (smueller@chronox.de) +.\" +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one. +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" License. +.TH JITTERENTROPY 3 2021-03-08 +.SH NAME +jitterentropy \- CPU Jitter Random Number Generator +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "int jent_entropy_switch_notime_impl(struct jent_notime_thread *" new_thread ); +.sp +.BI "int jent_set_fips_failure_callback(jent_fips_failure_cb " cb "); +.sp +.BI "int jent_entropy_init(" void "); +.sp +.BI "int jent_entropy_init_ex(unsigned int " osr ", unsigned int " flags ); +.sp +.BI "struct rand_data *jent_entropy_collector_alloc(unsigned int " osr ", +.BI " unsigned int " flags ); +.sp +.BI "void jent_entropy_collector_free(struct rand_data *" entropy_collector ); +.sp +.BI "ssize_t jent_read_entropy(struct rand_data *" entropy_collector ", +.BI " char *" data ", size_t " len ); +.sp +.BI "ssize_t jent_read_entropy_safe(struct rand_data **" entropy_collector ", +.BI " char *" data ", size_t " len ); +.sp +.BI "#define JENT_MAJVERSION x" +.sp +.BI "#define JENT_MINVERSION y" +.sp +.BI "#define JENT_PATCHLEVEL z" +.sp +.BI "#define JENT_VERSION (...)" +.sp +.BI "unsigned int jent_version(" void "); +.fi +.SH DESCRIPTION +The +.I jitterentropy +library provides a source of good entropy by collecting CPU +executing time jitter. The entropy in the CPU execution time +jitter is magnified by the CPU Jitter Random Number Generator. +The CPU Jitter Random Number Generator uses the CPU execution +timing jitter to generate a bit stream which complies with +different statistical measurements that determine the bit +stream is random. +.LP +The CPU Jitter Random Number Generator delivers entropy which +follows information theoretical requirements. Based on these +studies and the implementation, the caller can assume that +one bit of data extracted from the CPU Jitter Random Number +Generator holds one bit of entropy. +.LP +The CPU Jitter Random Number Generator provides a decentralized +source of entropy where the caller does not need to rely +on a centrally maintained source of entropy like +.IR /dev/random +or +.IR /dev/urandom . +.LP +.BR jent_entropy_switch_notime_impl () +allows the caller to set a thread handler that is used by the +Jitter RNG if it operates in the timer-less mode. See +.IR jitterentropy.h +for a documentation of +.IR new_thread . +This function must be called before +.BR jent_entropy_init () +as after this call, the change of the thread handler is denied. +.LP +.BR jent_set_fips_failure_callback () +allows the caller to set a callback that is invoked by the +Jitter RNG when a health test failure is detected. The callback +specified with the parameter +.BR cb +to the API function receives the Jitter RNG state with the parameter +.BR ec +and the FIPS health test failure with the parameter +.BR health_failure . +his function must be called before +.BR jent_entropy_init () +as after this call, the change of the callback is denied. +.LP +.BR jent_entropy_init () +initializes the CPU Jitter Random Number Generator. The function +performs statistical tests to verify that the underlying system +offers the properties needed for measuring and collecting entropy. +If the initialization is successful, which implies that the +statistical tests indicate the underlying system is appropriate, +the call returns with +.IR 0 . +A return code other than +.IR 0 +indicates a failure where the calling application +.B MUST NOT +use the CPU Jitter Random Number Generator. +.LP +.BR jent_entropy_init_ex () +behaves identically to +.BR jent_entropy_init () +except that it allows the caller to provide the +.IR osr +and +.IR flags +parameters which should be identical to the subsequent invocation of +.BR jent_entropy_collector_alloc (). +When specifying an oversampling rate +.IR osr +different than the default, the startup test honor this value and adjust +the self-test cut-off thresholds to the same values as used at runtime. +.LP +.BR jent_entropy_collector_alloc () +allocates a CPU Jitter entropy collector instance and returns the handle +to the caller. If the allocation fails, including memory +constraints, the call returns +.IR NULL . +The function requires two arguments, the oversampling rate +.IR osr +and a set of flags with +.IR flags . +The +.IR osr +value defines the amount of oversampling performed by the entropy +collector. Usually, a caller wants to provide the value 0 here to +apply the default oversampling. The call ensures that any value +lower than +.B JENT_MIN_OSR +is converted to +.B JENT_MIN_OSR +automatically. +.LP +The +.IR flags +value is either zero or one or more of the following flags. +.TP +.B JENT_DISABLE_MEMORY_ACCESS +If the system is constrained with memory, this flag +disables the allocation of that memory and therefore memory accesses. But +that also implies that the entropy collection process only relies on the +complexity of the CPU. Note, if somebody knows all details of that CPU +complexity, that person may potentially reduce the entropy delivered by the CPU +complexity. If that person can push the generated entropy below a threshold, +the CPU Jitter random number generator starts overestimating entropy from the +noise source. Thus, disabling memory accesses and relying only on the CPU +complexity should only be done if you really know what you are doing. +.TP +.B JENT_FORCE_INTERNAL_TIMER +This flag can be used to force the Jitter RNG to use the internal +high-resolution timer instead of using the hardware time stamp. Commonly, +the startup self test performed with +.BR jent_entropy_init () +uses the hardware timer with precedence if it is identified to be appropriate +for entropy collection. If the internal timer is not compiled, requesting +this flag returns an error. Even though a separate thread is spawned +to provide a high-resolution time stamp, this entire operation is completely +thread-safe as all relevant data is maintained as part of the +.IR entropy_collector +data structure. +.TP +.B JENT_DISABLE_INTERNAL_TIMER +This flag can be used to ensure that the internal timer is not used. +If this flag is used together with +.B JENT_FORCE_INTERNAL_TIMER +this is treated as an error and the allocation returns NULL. Also, +in case +.BR jent_entropy_init () +detects that the internal timer shall be used but the disable flag +is set, the allocation returns NULL. +.TP +.B JENT_FORCE_FIPS +Force full FIPS 140 and SP800-90B compliance irrespective of the +FIPS setting of the underlying operating system. +.TP +.B JENT_MAX_MEMSIZE_* +Define the maximum amount of memory that the Jitter RNG will use +for its operation supporting the collection of raw noise. Without +using one of these flags, the Jitter RNG uses a built-in limit. +The larger the amount of memory is the more entropy is collected. +Yet, the default value is safe on most CPUs. If you have memory +pressure but the entropy rate of your CPU is sufficient a lower +memory size may be used. Contrary when having sufficient memory +but insufficient entropy, larger memory sizes may be specified. +In any case, the Jitter RNG uses at most as much memory as the +sum of the CPU's data caches. +.LP +.BR jent_entropy_collector_free() +zeroizes and frees the given CPU Jitter entropy collector instance. +.LP +.BR jent_read_entropy () +generates a random bit stream and returns it to the caller. +.IR entropy_collector +is the CPU Jitter entropy collector instance which shall be used +to obtain random numbers. +.IR data +is the destination memory location where the random bit stream +is written to. The memory must have already been allocated by the +caller. +.IR len +is a length value provided by the caller indicating the number +of bytes the CPU Jitter Random Number Generator shall generate. +The caller can provide any value greater than 0. The caller +must ensure that +.IR data +is at least als big as +.IR len +indicates. The function returns the number of bytes generated +when the request is successfully completed. If the function returns +the error code +.IR -1 +then the caller handed in a non-initialized (i.e. NULL value) +for the entropy collector. The return code of +.IR -2 +indicates the SP800-90B repetition count online health test failed. +The error code of +.IR -3 +specifies that the SP800-90B adaptive proportion online health test +failed. +.IR -4 +marks that the internal timer generator cannot be initialized. +.IR -5 +specifies that the LAG predictor health test failed. +.IR -6 +indicates that the Repetitive Count Test (RCT) failed permanently. +.IR -7 +indicates that the Adaptive Proportion Test (APT) failed permanently. +.IR -8 +indicates that the LAG prediction test failed permanently. +.LP +When either online health test fails the Jitter RNG will not +have any data provided in +.IR data . +The entropy collector instance will remain in error state. To recover, +the entropy collector instance +.B MUST +be deallocated and a fresh instance must be allocated. It is +recommended that you increase the +.IR osr +value at least by one when newly allocating the Jitter RNG with +.BR jent_entropy_collector_alloc () +which implies that the health tests are less sensitive due to the +fact that the assumed entropy rate of the noise source is lower. +.LP +.BR jent_read_entropy_safe () +is a service function to and therefore operates identically to +.BR jent_read_entropy () +with the exception that it automatically re-allocates the entropy collector +if a health test failure is observed. Before reallocation, a +new power-on health test is performed. The allocation of the new entropy +collector automatically increases the OSR by one. This is done based +on the idea that a health test failure indicates that the assumed +entropy rate is too high. +.LP +Note the function returns with an health test error if the OSR is +getting too large. If an error is returned by this function, the Jitter +RNG is not safe to be used on the current system. +.LP +The function +.BR jent_read_entropy_safe () +has the same error codes as +.BR jent_read_entropy (). +.LP +.BR JENT_MAJVERSION +indicates API / ABI incompatible changes, functional changes that require +consumer to be updated. +.LP +.BR JENT_MINVERSION +indicates API compatible, ABI may change, functional enhancements only, +consumer can be left unchanged if enhancements are not considered. +.LP +.BR JENT_PATCHLEVEL +indicates API / ABI compatible, no functional changes, no enhancements, bug +fixes only. Also, the entropy collection is not changed in any way that +would necessitate a re-assessment. +.LP +.BR JENT_VERSION +the version number of the library as an integer value that is monotonically +increasing. 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. +.LP +.BR jent_version () +returns +.BR JENT_VERSION. +.PP +.SH FIPS 140-3 Considerations +In order for the Jitter RNG to execute compliant to FIPS 140-3 and by +extension also SP800-90B and SP800-90C compliant, the following +considerations must be applied: +.TP +.B Enable FIPS mode +The FIPS mode is enabled by using the +.IR JENT_FORCE_FIPS +flag during initialization of the Jitter RNG library. On Linux, the +the FIPS mode is transparently enabled if the entire operating system +was booted in FIPS mode, usually by using the "fips=1" Linux kernel +command line parameter. +.TP +.B Perform heursitic entropy analysis +The test tool set provided as part of the Jitter RNG library source +distribution contains the helper to obtain raw noise data at runtime +as well as at initialization time to calculate the SP800-90B entropy rate. +This rate must be above 0.333, the implied heuristic minimum by the Jitter +RNG library. +.TP +.B Resolve insufficient entropy +If insufficient entropy is found during the aforementioned SP800-90B +analysis, the test tool set provides a helper to analyze optimal +settings - see the test tool set for raw entropy for details. The resulting +configuration values are expected to be used with the +.IR flags +parameter of the calls +.BR jent_entropy_collector_alloc () +and +.BR jent_entropy_init_ex () . +It is recommended that the function +.BR jent_read_entropy_safe () +API call is used for generating random numbers. +.PP +.SH NOTES +In addition to use the generated random bit stream directly +for cryptographic operations, the output of +.BR jent_read_entropy () +can be used for seeding a deterministic random number generator. +.PP +.SH SEE ALSO +http://www.chronox.de provides the design description, +the entropy and statistical analyses as well as a number of +test cases. diff --git a/third_party/jitterentropy/jitterentropy-base-user.h b/third_party/jitterentropy/jitterentropy-base-user.h index 8898463e67..659a22c806 100644 --- a/third_party/jitterentropy/jitterentropy-base-user.h +++ b/third_party/jitterentropy/jitterentropy-base-user.h @@ -1,7 +1,7 @@ /* * Non-physical true random number generator based on timing jitter. * - * Copyright Stephan Mueller , 2013 - 2022 + * Copyright Stephan Mueller , 2013 - 2024 * * License * ======= @@ -49,15 +49,16 @@ * Compilation for OpenSSL #define OPENSSL */ +#include +#include + #include #include #include #include #include #include -#include -#include #include #include #include @@ -96,8 +97,9 @@ /* Support rdtsc read on 64-bit and 32-bit x86 architectures */ #ifdef __x86_64__ -# define DECLARE_ARGS(val, low, high) unsigned long low, high -# define EAX_EDX_VAL(val, low, high) (((uint64_t)low) | ((uint64_t)high) << 32) +/* specify 64 bit type since long is 32 bits in LLP64 x86_64 systems */ +# define DECLARE_ARGS(val, low, high) uint64_t low, high +# define EAX_EDX_VAL(val, low, high) ((low) | (high) << 32) # define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high) #elif __i386__ # define DECLARE_ARGS(val, low, high) unsigned long val @@ -108,7 +110,7 @@ static inline void jent_get_nstime(uint64_t *out) { DECLARE_ARGS(val, low, high); - __asm__ __volatile__("rdtsc" : EAX_EDX_RET(val, low, high)); + __asm__ __volatile__("rdtsc" : EAX_EDX_RET(val, low, high)); *out = EAX_EDX_VAL(val, low, high); } @@ -120,15 +122,100 @@ static inline void jent_get_nstime(uint64_t *out) /* * Use the system counter for aarch64 (64 bit ARM). */ - __asm__ volatile("mrs %0, cntvct_el0" : "=r" (ctr_val)); + __asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (ctr_val)); *out = ctr_val; } -#else /* (__x86_64__) || (__i386__) || (__aarch64__) */ +#elif defined(__s390x__) + +static inline void jent_get_nstime(uint64_t *out) +{ + /* + * This is MVS+STCK code! Enable it with -S in the compiler. + * + * uint64_t clk; + * __asm__ volatile("stck %0" : "=m" (clk) : : "cc"); + * *out = (uint64_t)(clk); + */ + + /* + * This is GCC+STCKE code. STCKE command and data format: + * z/Architecture - Principles of Operation + * http://publibz.boulder.ibm.com/epubs/pdf/dz9zr007.pdf + * + * The current value of bits 0-103 of the TOD clock is stored in bytes + * 1-13 of the sixteen-byte output: + * + * bits 0-7: zeros (reserved for future extention) + * bits 8-111: TOD Clock value + * bits 112-127: Programmable Field + * + * Output bit 59 (TOD-Clock bit 51) effectively increments every + * microsecond. Bits 60 to 111 of STCKE output are fractions of + * a miscrosecond: bit 59 is 1.0us, bit 60 is .5us, bit 61 is .25us, + * bit 62 is .125us, bit 63 is 62.5ns, etc. + * + * Some of these bits can be implemented, some not. 64 bits of + * the TOD clock are implemented usually nowadays, these are + * bits 8-71 of the output. + * + * The stepping value of TOD-clock bit position 63, if implemented, + * is 2^-12 microseconds, or approximately 244 picoseconds. This value + * is called a clock unit. + */ + + uint8_t clk[16]; + + __asm__ __volatile__("stcke %0" : "=Q" (clk) : : "cc"); + + /* s390x is big-endian, so just perfom a byte-by-byte copy */ + *out = *(uint64_t *)(clk + 1); +} + +#elif defined(__powerpc) +/* + * Uncomment this for newer PPC CPUs + * Newer PPC CPUs do not support mftbu/mftb + * these instructions were obsoleted and replaced by + * mfspr. special processor registers 268 and 269 are the + * ones we want. + */ + /* #define POWER_PC_USE_NEW_INSTRUCTIONS */ + +/* taken from http://www.ecrypt.eu.org/ebats/cpucycles.html */ + +static inline void jent_get_nstime(uint64_t *out) +{ + unsigned long high; + unsigned long low; + unsigned long newhigh; + uint64_t result; +#ifdef POWER_PC_USE_NEW_INSTRUCTIONS /* Newer PPC CPUs do not support mftbu/mftb */ + __asm__ __volatile__( + "Lcpucycles:mfspr %0, 269;mfspr %1, 268;mfspr %2, 269;cmpw %0,%2;bne Lcpucycles" + : "=r" (high), "=r" (low), "=r" (newhigh) + ); +#else + __asm__ __volatile__( + "Lcpucycles:mftbu %0;mftb %1;mftbu %2;cmpw %0,%2;bne Lcpucycles" + : "=r" (high), "=r" (low), "=r" (newhigh) + ); +#endif + result = high; + result <<= 32; + result |= low; + *out = result; +} + +#else /* (__x86_64__) || (__i386__) || (__aarch64__) || (__s390x__) || (__powerpc) */ static inline void jent_get_nstime(uint64_t *out) { -#ifdef _AIX + /* OSX does not have clock_gettime -- taken from + * http://developer.apple.com/library/mac/qa/qa1398/_index.html */ +# ifdef __MACH__ + *out = mach_absolute_time(); +# elif _AIX /* clock_gettime() on AIX returns a timer value that increments in * steps of 1000 */ @@ -139,7 +226,7 @@ static inline void jent_get_nstime(uint64_t *out) tmp = tmp << 32; tmp = tmp | aixtime.tb_low; *out = tmp; -# else /* __AIX */ +# else /* __MACH__ */ /* 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 @@ -152,7 +239,7 @@ static inline void jent_get_nstime(uint64_t *out) tmp = tmp + (uint64_t)time.tv_nsec; } *out = tmp; -# endif /* __AIX */ +# endif /* __MACH__ */ } #endif /* (__x86_64__) || (__i386__) || (__aarch64__) */ @@ -238,7 +325,7 @@ static inline void jent_memset_secure(void *s, size_t n) static inline long jent_ncpu(void) { -#ifdef _POSIX_SOURCE +#if defined(_POSIX_SOURCE) || defined(__APPLE__) long ncpu = sysconf(_SC_NPROCESSORS_ONLN); if (ncpu == -1) diff --git a/third_party/jitterentropy/jitterentropy.h b/third_party/jitterentropy/jitterentropy.h index 8e9372c792..266864ca6d 100644 --- a/third_party/jitterentropy/jitterentropy.h +++ b/third_party/jitterentropy/jitterentropy.h @@ -1,7 +1,7 @@ /* * Non-physical true random number generator based on timing jitter. * - * Copyright Stephan Mueller , 2014 - 2022 + * Copyright Stephan Mueller , 2014 - 2024 * * License * ======= @@ -46,6 +46,30 @@ extern "C" { #endif +/* + * 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 JENT_MAJVERSION 3 + +/* + * API compatible, ABI may change, functional enhancements only, consumer can be + * left unchanged if enhancements are not considered. + */ +#define JENT_MINVERSION 6 + +/* + * API / ABI compatible, no functional changes, no enhancements, bug fixes only. + * Also, the entropy collection is not changed in any way that would necessitate + * a re-assessment. + */ +#define JENT_PATCHLEVEL 0 + +#define JENT_VERSION (JENT_MAJVERSION * 1000000 + \ + JENT_MINVERSION * 10000 + \ + JENT_PATCHLEVEL * 100) + /*************************************************************************** * Jitter RNG Configuration Section * @@ -94,6 +118,46 @@ extern "C" { */ #define JENT_RANDOM_MEMACCESS +/* + * Mask specifying the number of bits of the raw entropy data of the time delta + * value used for the APT. + * + * This value implies that for the APT, only the bits specified by + * JENT_APT_MASK are taken. This was suggested in a draft IG D.K resolution 22 + * provided by NIST, but further analysis + * (https://www.untruth.org/~josh/sp80090b/CMUF%20EWG%20Draft%20IG%20D.K%20Comments%20D10.pdf) + * suggests that this truncation / translation generally results in a health + * test with both a higher false positive rate (because multiple raw symbols + * map to the same symbol within the health test) and a lower statistical power + * when the APT cutoff is selected based on the apparent truncated entropy + * (i.e., truncation generally makes the test worse). NIST has since withdrawn + * this draft and stated that they will not propose truncation prior to + * health testing. + * Because the general tendency of such truncation to make the health test + * worse the default value is set such that no data is masked out and this + * should only be changed if a hardware-specific analysis suggests that some + * other mask setting is beneficial. + * The mask is applied to a time stamp where the GCD is already divided out, and thus no + * "non-moving" low-order bits are present. + */ +#define JENT_APT_MASK (UINT64_C(0xffffffffffffffff)) + +/* This parameter establishes the multiplicative factor that the desired + * memory region size should be larger than the observed cache size; the + * multiplicative factor is 2^JENT_CACHE_SHIFT_BITS. + * Set this to 0 if the desired memory region should be at least as large as + * the cache. If one wants most of the memory updates to result in a memory + * update, then this value should be at least 1. + * If the memory updates should dominantly result in a memory update, then + * the value should be set to at least 3. + * The actual size of the memory region is never larger than requested by + * the passed in JENT_MAX_MEMSIZE_* flag (if provided) or JENT_MEMORY_SIZE + * (if no JENT_MAX_MEMSIZE_* flag is provided). + */ +#ifndef JENT_CACHE_SHIFT_BITS +#define JENT_CACHE_SHIFT_BITS 0 +#endif + /*************************************************************************** * Jitter RNG State Definition Section ***************************************************************************/ @@ -104,8 +168,8 @@ extern "C" { #include "jitterentropy-base-user.h" #endif -#define SHA3_256_SIZE_DIGEST_BITS 256 -#define SHA3_256_SIZE_DIGEST (SHA3_256_SIZE_DIGEST_BITS >> 3) +#define JENT_SHA3_256_SIZE_DIGEST_BITS 256 +#define JENT_SHA3_256_SIZE_DIGEST (JENT_SHA3_256_SIZE_DIGEST_BITS >> 3) /* * The output 256 bits can receive more than 256 bits of min entropy, @@ -129,7 +193,7 @@ extern "C" { * The external caller provides these function pointers to handle the * management of the timer thread that is spawned by the Jitter RNG. * - * @var jent_notime_init This function is intended to initialze the threading + * @var jent_notime_init This function is intended to initialize the threading * support. All data that is required by the threading code must be * held in the data structure @param ctx. The Jitter RNG maintains the * data structure and uses it for every invocation of the following calls. @@ -175,7 +239,7 @@ struct rand_data * calculate the next random value. */ void *hash_state; /* SENSITIVE hash state entropy pool */ uint64_t prev_time; /* SENSITIVE Previous time stamp */ -#define DATA_SIZE_BITS (SHA3_256_SIZE_DIGEST_BITS) +#define DATA_SIZE_BITS (JENT_SHA3_256_SIZE_DIGEST_BITS) #ifndef JENT_HEALTH_LAG_PREDICTOR uint64_t last_delta; /* SENSITIVE stuck test */ @@ -222,8 +286,8 @@ struct rand_data int rct_count; /* Number of stuck values */ /* Adaptive Proportion Test for a significance level of 2^-30 */ - unsigned int apt_cutoff; /* Calculated using a corrected version - * of the SP800-90B sec 4.4.2 formula */ + unsigned int apt_cutoff; /* Intermittent health test failure */ + unsigned int apt_cutoff_permanent; /* Permanent health test failure */ #define JENT_APT_WINDOW_SIZE 512 /* Data window size */ unsigned int apt_observations; /* Number of collected observations in * current window. */ @@ -345,20 +409,6 @@ struct rand_data # define JENT_MIN_OSR 1 #endif -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -/* -- 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*9) / 10) -#endif - #ifdef JENT_PRIVATE_COMPILE # define JENT_PRIVATE_STATIC static #else /* JENT_PRIVATE_COMPILE */ @@ -453,6 +503,11 @@ static inline void jent_notime_fini(void *ctx) { (void)ctx; } #define JENT_RCT_FAILURE 1 /* Failure in RCT health test. */ #define JENT_APT_FAILURE 2 /* Failure in APT health test. */ #define JENT_LAG_FAILURE 4 /* Failure in Lag predictor health test. */ +#define JENT_PERMANENT_FAILURE_SHIFT 16 +#define JENT_PERMANENT_FAILURE(x) (x << JENT_PERMANENT_FAILURE_SHIFT) +#define JENT_RCT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_RCT_FAILURE) +#define JENT_APT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_APT_FAILURE) +#define JENT_LAG_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_LAG_FAILURE) /* -- END error masks for health tests -- */ /* -- BEGIN statistical test functions only complied with CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT -- */ diff --git a/third_party/jitterentropy/jitterentropy-base.c b/third_party/jitterentropy/src/jitterentropy-base.c similarity index 89% rename from third_party/jitterentropy/jitterentropy-base.c rename to third_party/jitterentropy/src/jitterentropy-base.c index f2e79bd4ec..4790ee5b29 100644 --- a/third_party/jitterentropy/jitterentropy-base.c +++ b/third_party/jitterentropy/src/jitterentropy-base.c @@ -1,7 +1,7 @@ /* * Non-physical true random number generator based on timing jitter. * - * Copyright Stephan Mueller , 2014 - 2022 + * Copyright Stephan Mueller , 2014 - 2024 * * Design * ====== @@ -29,25 +29,14 @@ * DAMAGE. */ -#include "jitterentropy.h" - #include "jitterentropy-base.h" #include "jitterentropy-gcd.h" #include "jitterentropy-health.h" +#include "jitterentropy-internal.h" #include "jitterentropy-noise.h" #include "jitterentropy-timer.h" #include "jitterentropy-sha3.h" -#define MAJVERSION 3 /* 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 4 /* 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 */ - /*************************************************************************** * Jitter RNG Static Definitions * @@ -82,13 +71,7 @@ JENT_PRIVATE_STATIC unsigned int jent_version(void) { - unsigned int version = 0; - - version = MAJVERSION * 1000000; - version += MINVERSION * 10000; - version += PATCHLEVEL * 100; - - return version; + return JENT_VERSION; } /*************************************************************************** @@ -162,9 +145,12 @@ static inline unsigned int jent_update_memsize(unsigned int flags) * The following error codes can occur: * -1 entropy_collector is NULL * -2 RCT failed - * -3 APT test failed + * -3 APT failed * -4 The timer cannot be initialized * -5 LAG failure + * -6 RCT permanent failure + * -7 APT permanent failure + * -8 LAG permanent failure */ JENT_PRIVATE_STATIC ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len) @@ -186,7 +172,15 @@ ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len) jent_random_data(ec); if ((health_test_result = jent_health_failure(ec))) { - if (health_test_result & JENT_RCT_FAILURE) + if (health_test_result & JENT_RCT_FAILURE_PERMANENT) + ret = -6; + else if (health_test_result & + JENT_APT_FAILURE_PERMANENT) + ret = -7; + else if (health_test_result & + JENT_LAG_FAILURE_PERMANENT) + ret = -8; + else if (health_test_result & JENT_RCT_FAILURE) ret = -2; else if (health_test_result & JENT_APT_FAILURE) ret = -3; @@ -276,7 +270,12 @@ ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len) return -1; while (len > 0) { - unsigned int osr, flags, max_mem_set; + unsigned int osr, flags, max_mem_set, apt_count, + apt_observations = 0, + lag_prediction_success_run, + lag_prediction_success_count; + int rct_count; + uint64_t current_delta; ret = jent_read_entropy(*ec, p, len); @@ -287,6 +286,19 @@ ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len) case -2: case -3: case -5: + apt_count = (*ec)->apt_count; + apt_observations = (*ec)->apt_observations; + current_delta = (*ec)->apt_base; + rct_count = (*ec)->rct_count; + lag_prediction_success_run = + (*ec)->lag_prediction_success_run; + lag_prediction_success_count = + (*ec)->lag_prediction_success_count; + + JE_FALLTHROUGH; + case -6: + case -7: + case -8: osr = (*ec)->osr + 1; flags = (*ec)->flags; max_mem_set = (*ec)->max_mem_set; @@ -308,10 +320,14 @@ ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len) * memory size */ jent_entropy_collector_free(*ec); + *ec = NULL; /* Perform new health test with updated OSR */ - if (jent_entropy_init_ex(osr, flags)) - return -1; + while (jent_entropy_init_ex(osr, flags)) { + osr++; + if (osr > 20) + return -1; + } *ec = _jent_entropy_collector_alloc(osr, flags); if (!*ec) @@ -320,6 +336,32 @@ ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len) /* Remember whether caller configured memory size */ (*ec)->max_mem_set = !!max_mem_set; + /* + * Set the health test state in case of intermittent + * failures. + */ + if (apt_observations) { + /* APT re-initialization */ + jent_apt_reinit(*ec, current_delta, apt_count, + apt_observations); + + /* RCT re-initialization */ + (*ec)->rct_count = rct_count; + + /* LAG re-initialization */ + (*ec)->lag_prediction_success_run = + lag_prediction_success_run; + (*ec)->lag_prediction_success_count = + lag_prediction_success_count; + } + + /* + * We are not returning the intermittent or permanent + * errors here. If a caller wants them, he should + * register a callback with + * jent_set_fips_failure_callback. + */ + break; default: @@ -358,7 +400,7 @@ ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len) */ static inline uint32_t jent_memsize(unsigned int flags) { - uint32_t memsize, max_memsize; + uint32_t cache_memsize=0, max_memsize=0, memsize=0; max_memsize = JENT_FLAGS_TO_MAX_MEMSIZE(flags); @@ -370,7 +412,11 @@ static inline uint32_t jent_memsize(unsigned int flags) } /* Allocate memory for adding variations based on memory access */ - memsize = jent_cache_size_roundup(); + cache_memsize = jent_cache_size_roundup(); + memsize = cache_memsize << JENT_CACHE_SHIFT_BITS; + /* If this value is left-shifted too much, it may be cleared. */ + /* If so, set the maximum possible power of two. */ + if (cache_memsize > memsize) memsize = 0x80000000; /* Limit the memory as defined by caller */ memsize = (memsize > max_memsize) ? max_memsize : memsize; @@ -440,11 +486,11 @@ static struct rand_data entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS; } - if (sha3_alloc(&entropy_collector->hash_state)) + if (jent_sha3_alloc(&entropy_collector->hash_state)) goto err; /* Initialize the hash state */ - sha3_256_init(entropy_collector->hash_state); + jent_sha3_256_init(entropy_collector->hash_state); /* verify and set the oversampling rate */ if (osr < JENT_MIN_OSR) @@ -485,6 +531,8 @@ static struct rand_data err: if (entropy_collector->mem != NULL) jent_zfree(entropy_collector->mem, memsize); + if (entropy_collector->hash_state != NULL) + jent_sha3_dealloc(entropy_collector->hash_state); jent_zfree(entropy_collector, sizeof(struct rand_data)); return NULL; } @@ -526,7 +574,7 @@ JENT_PRIVATE_STATIC void jent_entropy_collector_free(struct rand_data *entropy_collector) { if (entropy_collector != NULL) { - sha3_dealloc(entropy_collector->hash_state); + jent_sha3_dealloc(entropy_collector->hash_state); jent_notime_disable(entropy_collector); if (entropy_collector->mem != NULL) { jent_zfree(entropy_collector->mem, @@ -682,7 +730,7 @@ static inline int jent_entropy_init_common_pre(void) jent_notime_block_switch(); jent_health_cb_block_switch(); - if (sha3_tester()) + if (jent_sha3_tester()) return EHASH; ret = jent_gcd_selftest(); diff --git a/third_party/jitterentropy/jitterentropy-base.h b/third_party/jitterentropy/src/jitterentropy-base.h similarity index 94% rename from third_party/jitterentropy/jitterentropy-base.h rename to third_party/jitterentropy/src/jitterentropy-base.h index 1451e77b7e..3eea8c7f19 100644 --- a/third_party/jitterentropy/jitterentropy-base.h +++ b/third_party/jitterentropy/src/jitterentropy-base.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * diff --git a/third_party/jitterentropy/jitterentropy-gcd.c b/third_party/jitterentropy/src/jitterentropy-gcd.c similarity index 96% rename from third_party/jitterentropy/jitterentropy-gcd.c rename to third_party/jitterentropy/src/jitterentropy-gcd.c index 0b32712914..6a90c8cb03 100644 --- a/third_party/jitterentropy/jitterentropy-gcd.c +++ b/third_party/jitterentropy/src/jitterentropy-gcd.c @@ -1,7 +1,7 @@ /* Jitter RNG: GCD health test * - * Copyright (C) 2021 - 2022, Joshua E. Hill - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Joshua E. Hill + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -19,8 +19,8 @@ * DAMAGE. */ -#include "jitterentropy.h" #include "jitterentropy-gcd.h" +#include "jitterentropy-internal.h" /* The common divisor for all timestamp deltas */ static uint64_t jent_common_timer_gcd = 0; diff --git a/third_party/jitterentropy/jitterentropy-gcd.h b/third_party/jitterentropy/src/jitterentropy-gcd.h similarity index 92% rename from third_party/jitterentropy/jitterentropy-gcd.h rename to third_party/jitterentropy/src/jitterentropy-gcd.h index 6eb1b7e954..64c9709ace 100644 --- a/third_party/jitterentropy/jitterentropy-gcd.h +++ b/third_party/jitterentropy/src/jitterentropy-gcd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -20,6 +20,8 @@ #ifndef JITTERENTROPY_GCD_H #define JITTERENTROPY_GCD_H +#include "jitterentropy-internal.h" + #ifdef __cplusplus extern "C" { diff --git a/third_party/jitterentropy/jitterentropy-health.c b/third_party/jitterentropy/src/jitterentropy-health.c similarity index 86% rename from third_party/jitterentropy/jitterentropy-health.c rename to third_party/jitterentropy/src/jitterentropy-health.c index bcc9d04f56..c4c37e72ce 100644 --- a/third_party/jitterentropy/jitterentropy-health.c +++ b/third_party/jitterentropy/src/jitterentropy-health.c @@ -1,7 +1,7 @@ /* Jitter RNG: Health Tests * - * Copyright (C) 2021 - 2022, Joshua E. Hill - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Joshua E. Hill + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -86,6 +86,7 @@ void jent_lag_init(struct rand_data *ec, unsigned int osr) * Establish the lag global and local cutoffs based on the presumed * entropy rate of 1/osr. */ + /* TODO: add permanent health failure */ if (osr > ARRAY_SIZE(jent_lag_global_cutoff_lookup)) { ec->lag_global_cutoff = jent_lag_global_cutoff_lookup[ @@ -115,7 +116,7 @@ static void jent_lag_reset(struct rand_data *ec) /* Reset Lag counters */ ec->lag_prediction_success_count = 0; ec->lag_prediction_success_run = 0; - ec->lag_best_predictor = 0; //The first guess is basically arbitrary. + ec->lag_best_predictor = 0; /* The first guess is basically arbitrary. */ ec->lag_observations = 0; for (i = 0; i < JENT_LAG_HISTORY_SIZE; i++) { @@ -161,6 +162,7 @@ static void jent_lag_insert(struct rand_data *ec, uint64_t current_delta) ec->lag_prediction_success_count++; ec->lag_prediction_success_run++; + /* TODO: add permanent health failure */ if ((ec->lag_prediction_success_run >= ec->lag_local_cutoff) || (ec->lag_prediction_success_count >= ec->lag_global_cutoff)) ec->health_failure |= JENT_LAG_FAILURE; @@ -264,6 +266,10 @@ static inline uint64_t jent_delta3(struct rand_data *ec, uint64_t delta2) * necessarily have been observed, so there is no chance of observing 0 of these * symbols.) * + * For the alpha < 2^-53, R cannot be used as it uses a float data type without + * arbitrary precision. A SageMath script is used to calculate those cutoff + * values. + * * For any value above 14, this yields the maximal allowable value of 512 * (by FIPS 140-2 IG 7.19 Resolution # 16, we cannot choose a cutoff value that * renders the test unable to fail). @@ -271,6 +277,9 @@ static inline uint64_t jent_delta3(struct rand_data *ec, uint64_t delta2) static const unsigned int jent_apt_cutoff_lookup[15]= { 325, 422, 459, 477, 488, 494, 499, 502, 505, 507, 508, 509, 510, 511, 512 }; +static const unsigned int jent_apt_cutoff_permanent_lookup[15]= + { 355, 447, 479, 494, 502, 507, 510, 512, + 512, 512, 512, 512, 512, 512, 512 }; void jent_apt_init(struct rand_data *ec, unsigned int osr) { @@ -280,12 +289,32 @@ void jent_apt_init(struct rand_data *ec, unsigned int osr) */ if (osr >= ARRAY_SIZE(jent_apt_cutoff_lookup)) { ec->apt_cutoff = jent_apt_cutoff_lookup[ - ARRAY_SIZE(jent_apt_cutoff_lookup) - 1]; + ARRAY_SIZE(jent_apt_cutoff_lookup) - 1]; + ec->apt_cutoff_permanent = jent_apt_cutoff_permanent_lookup[ + ARRAY_SIZE(jent_apt_cutoff_permanent_lookup) - 1]; } else { ec->apt_cutoff = jent_apt_cutoff_lookup[osr - 1]; + ec->apt_cutoff_permanent = + jent_apt_cutoff_permanent_lookup[osr - 1]; } } +void jent_apt_reinit(struct rand_data *ec, + uint64_t current_delta, + unsigned int apt_count, + unsigned int apt_observations) +{ + ec->apt_base = current_delta; /* APT Step 1 */ + ec->apt_base_set = 1; /* APT Step 2 */ + + /* + * Reset APT counter + * Note that we've taken in the first symbol in the window. + */ + ec->apt_count = apt_count; + ec->apt_observations = apt_observations; +} + /** * Reset the APT counter * @@ -305,26 +334,21 @@ static void jent_apt_reset(struct rand_data *ec) */ static void jent_apt_insert(struct rand_data *ec, uint64_t current_delta) { + current_delta &= JENT_APT_MASK; + /* Initialize the base reference */ if (!ec->apt_base_set) { - ec->apt_base = current_delta; // APT Step 1 - ec->apt_base_set = 1; // APT Step 2 - - /* - * Reset APT counter - * Note that we've taken in the first symbol in the window. - */ - ec->apt_count = 1; // B = 1 - ec->apt_observations = 1; - + jent_apt_reinit(ec, current_delta, 1, 1); return; } if (current_delta == ec->apt_base) { - ec->apt_count++; // B = B + 1 + ec->apt_count++; /* B = B + 1 */ /* Note, ec->apt_count starts with one. */ - if (ec->apt_count >= ec->apt_cutoff) + if (ec->apt_count >= ec->apt_cutoff_permanent) + ec->health_failure |= JENT_APT_FAILURE_PERMANENT; + else if (ec->apt_count >= ec->apt_cutoff) ec->health_failure |= JENT_APT_FAILURE; } @@ -332,7 +356,7 @@ static void jent_apt_insert(struct rand_data *ec, uint64_t current_delta) /* Completed one window, the next symbol input will be new apt_base. */ if (ec->apt_observations >= JENT_APT_WINDOW_SIZE) - jent_apt_reset(ec); // APT Step 4 + jent_apt_reset(ec); /* APT Step 4 */ } /*************************************************************************** @@ -343,7 +367,8 @@ static void jent_apt_insert(struct rand_data *ec, uint64_t current_delta) * back-to-back values, the input to the RCT is the counting of the stuck * values during the generation of one Jitter RNG output block. * - * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8. + * The RCT is applied with an alpha of 2^{-30} compliant to SP800-90B section + * 4.2 for the intermittent failure and 2^{-60} for permanent failures. * * During the counting operation, the Jitter RNG always calculates the RCT * cut-off value of C. If that value exceeds the allowed cut-off value, @@ -371,7 +396,7 @@ static void jent_rct_insert(struct rand_data *ec, int stuck) /* * The cutoff value is based on the following consideration: - * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8. + * alpha = 2^-30 or 2^-60 as recommended in SP800-90B. * In addition, we require an entropy value H of 1/osr as this * is the minimum entropy required to provide full entropy. * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr @@ -382,9 +407,13 @@ static void jent_rct_insert(struct rand_data *ec, int stuck) * Note, ec->rct_count (which equals to value B in the pseudo * code of SP800-90B section 4.4.1) starts with zero. Hence * we need to subtract one from the cutoff value as calculated - * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr. + * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr + * or 60*osr. */ - if ((unsigned int)ec->rct_count >= (30 * ec->osr)) { + if ((unsigned int)ec->rct_count >= (60 * ec->osr)) { + ec->rct_count = -1; + ec->health_failure |= JENT_RCT_FAILURE_PERMANENT; + } else if ((unsigned int)ec->rct_count >= (30 * ec->osr)) { ec->rct_count = -1; ec->health_failure |= JENT_RCT_FAILURE; } @@ -442,6 +471,9 @@ unsigned int jent_stuck(struct rand_data *ec, uint64_t current_delta) * 1 RCT failure * 2 APT failure * 4 Lag predictor test failure + * 1< + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -20,7 +20,7 @@ #ifndef JITTERENTROPY_HEALTH_H #define JITTERENTROPY_HEALTH_H -#include "jitterentropy.h" +#include "jitterentropy-internal.h" #ifdef __cplusplus extern "C" @@ -46,6 +46,10 @@ static inline void jent_lag_init(struct rand_data *ec, unsigned int osr) #endif /* JENT_HEALTH_LAG_PREDICTOR */ void jent_apt_init(struct rand_data *ec, unsigned int osr); +void jent_apt_reinit(struct rand_data *ec, + uint64_t current_delta, + unsigned int apt_count, + unsigned int apt_observations); unsigned int jent_stuck(struct rand_data *ec, uint64_t current_delta); unsigned int jent_health_failure(struct rand_data *ec); diff --git a/third_party/jitterentropy/src/jitterentropy-internal.h b/third_party/jitterentropy/src/jitterentropy-internal.h new file mode 100644 index 0000000000..ec146b6e9e --- /dev/null +++ b/third_party/jitterentropy/src/jitterentropy-internal.h @@ -0,0 +1,88 @@ +/* + * Non-physical true random number generator based on timing jitter. + * + * Copyright Stephan Mueller , 2014 - 2024 + * + * 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_INTERNAL_H +#define _JITTERENTROPY_INTERNAL_H + +#include "jitterentropy.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Portable switch fall-through to silence warnings. Only works for C. */ +#if defined(__GNUC__) && __GNUC__ >= 7 // gcc 7 +#define JE_FALLTHROUGH __attribute__ ((fallthrough)) +#elif defined(__clang__) +/* Separate logic to avoid errors when compiler doesn't understand __has_attribute */ +#if __has_attribute(fallthrough) && __clang_major__ >= 5 +/* + * Clang 3.5, at least, complains about "error: declaration does not declare + * anything", possibly because we put a semicolon after this macro in + * practice. Thus limit it to >= Clang 5, which does work. + */ +#define JE_FALLTHROUGH __attribute__ ((fallthrough)) +#else +#define JE_FALLTHROUGH +#endif +#else +#define JE_FALLTHROUGH +#endif + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* -- 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*9) / 10) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _JITTERENTROPY_INTERNAL_H */ diff --git a/third_party/jitterentropy/jitterentropy-noise.c b/third_party/jitterentropy/src/jitterentropy-noise.c similarity index 77% rename from third_party/jitterentropy/jitterentropy-noise.c rename to third_party/jitterentropy/src/jitterentropy-noise.c index 5537f72bcb..755f9580df 100644 --- a/third_party/jitterentropy/jitterentropy-noise.c +++ b/third_party/jitterentropy/src/jitterentropy-noise.c @@ -1,6 +1,6 @@ /* Jitter RNG: Noise Sources * - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -33,34 +33,43 @@ * Update of the loop count used for the next round of * an entropy collection. * + * @ec [in] entropy collector struct * @bits [in] is the number of low bits of the timer to consider * @min [in] 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(unsigned int bits, unsigned int min) +static uint64_t jent_loop_shuffle(struct rand_data *ec, + unsigned int bits, unsigned int min) { #ifdef JENT_CONF_DISABLE_LOOP_SHUFFLE + (void)ec; (void)bits; return (UINT64_C(1)< i; i++) { - shuffle ^= time & mask; - time = time >> bits; + for (i = 0; (((sizeof(time_now) << 3) + bits - 1) / bits) > i; i++) { + shuffle ^= time_now & mask; + time_now = time_now >> bits; } /* @@ -79,7 +88,7 @@ static uint64_t jent_loop_shuffle(unsigned int bits, unsigned int min) * This function injects the individual bits of the time value into the * entropy pool using a hash. * - * @ec [in] entropy collector struct -- may be NULL + * @ec [in] entropy collector struct * @time_delta [in] time delta to be injected * @loop_cnt [in] if a value not equal to 0 is set, use the given value as * number of loops to perform the hash operation @@ -92,20 +101,22 @@ static void jent_hash_time(struct rand_data *ec, uint64_t time_delta, uint64_t loop_cnt, unsigned int stuck) { HASH_CTX_ON_STACK(ctx); - uint8_t intermediary[SHA3_256_SIZE_DIGEST]; - uint64_t j = 0; + /* Size of intermediary ensures a Keccak operation during hash_update */ + uint8_t intermediary[JENT_SHA3_MAX_SIZE_BLOCK] = { 0 }; + uint64_t j = 0, output_value; #define MAX_HASH_LOOP 3 #define MIN_HASH_LOOP 0 /* Ensure that macros cannot overflow jent_loop_shuffle() */ BUILD_BUG_ON((MAX_HASH_LOOP + MIN_HASH_LOOP) > 63); uint64_t hash_loop_cnt = - jent_loop_shuffle(MAX_HASH_LOOP, MIN_HASH_LOOP); + jent_loop_shuffle(ec, MAX_HASH_LOOP, MIN_HASH_LOOP); - /* Use the memset to shut up valgrind */ - memset(intermediary, 0, sizeof(intermediary)); + /* Ensure that everything will fit into the intermediary buffer. */ + BUILD_BUG_ON(sizeof(intermediary) < (JENT_SHA3_256_SIZE_DIGEST + + sizeof(uint64_t))); - sha3_256_init(&ctx); + jent_sha3_256_init(&ctx); /* * testing purposes -- allow test app to set the counter, not @@ -128,40 +139,52 @@ static void jent_hash_time(struct rand_data *ec, uint64_t time_delta, * the sha3_final. */ for (j = 0; j < hash_loop_cnt; j++) { - sha3_update(&ctx, intermediary, sizeof(intermediary)); - sha3_update(&ctx, (uint8_t *)&ec->rct_count, - sizeof(ec->rct_count)); - sha3_update(&ctx, (uint8_t *)&ec->apt_cutoff, - sizeof(ec->apt_cutoff)); - sha3_update(&ctx, (uint8_t *)&ec->apt_observations, - sizeof(ec->apt_observations)); - sha3_update(&ctx, (uint8_t *)&ec->apt_count, - sizeof(ec->apt_count)); - sha3_update(&ctx,(uint8_t *) &ec->apt_base, - sizeof(ec->apt_base)); - sha3_update(&ctx, (uint8_t *)&j, sizeof(uint64_t)); - sha3_final(&ctx, intermediary); + jent_sha3_update(&ctx, intermediary, JENT_SHA3_256_SIZE_DIGEST); + jent_sha3_update(&ctx, (uint8_t *)&ec->rct_count, + sizeof(ec->rct_count)); + jent_sha3_update(&ctx, (uint8_t *)&ec->apt_cutoff, + sizeof(ec->apt_cutoff)); + jent_sha3_update(&ctx, (uint8_t *)&ec->apt_observations, + sizeof(ec->apt_observations)); + jent_sha3_update(&ctx, (uint8_t *)&ec->apt_count, + sizeof(ec->apt_count)); + jent_sha3_update(&ctx,(uint8_t *) &ec->apt_base, + sizeof(ec->apt_base)); + jent_sha3_update(&ctx, (uint8_t *)&j, sizeof(uint64_t)); + jent_sha3_final(&ctx, intermediary); } /* - * Inject the data from the previous loop into the pool. This data is - * not considered to contain any entropy, but it stirs the pool a bit. - */ - sha3_update(ec->hash_state, intermediary, sizeof(intermediary)); - - /* - * Insert the time stamp into the hash context representing the pool. + * Insert the time stamp into the intermediary buffer after the message + * digest of the intermediate data. * * If the time stamp is stuck, do not finally insert the value into the - * entropy pool. Although this operation should not do any harm even - * when the time stamp has no entropy, SP800-90B requires that any + * intermediary buffer. Although this operation should not do any harm + * even when the time stamp has no entropy, SP800-90B requires that any * conditioning operation to have an identical amount of input data * according to section 3.1.5. */ - if (!stuck) - sha3_update(ec->hash_state, (uint8_t *)&time_delta, sizeof(uint64_t)); + if (!stuck) { + /* Insert the time. */ + output_value = time_delta; + } else { + /* The time is considered stuck. Insert the fixed value 0. */ + output_value = 0; + } + + memcpy(intermediary + JENT_SHA3_256_SIZE_DIGEST, + (uint8_t *)&output_value, sizeof(uint64_t)); + + /* + * Inject the data from the intermediary buffer, including the hash we + * are using for timing, and (if the timer is not stuck) the time stamp. + * Only the time is considered to contain any entropy. The intermediary + * buffer is exactly SHA3-256-rate-size to always cause a Keccak + * operation. + */ + jent_sha3_update(ec->hash_state, intermediary, sizeof(intermediary)); - jent_memset_secure(&ctx, SHA_MAX_CTX_SIZE); + jent_memset_secure(&ctx, JENT_SHA_MAX_CTX_SIZE); jent_memset_secure(intermediary, sizeof(intermediary)); } @@ -193,7 +216,7 @@ static inline uint32_t xoshiro128starstar(uint32_t *s) static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) { - uint64_t i = 0, time_delta = 0; + uint64_t i = 0, time_now = 0; union { uint32_t u[4]; uint8_t b[sizeof(uint32_t) * 4]; @@ -203,7 +226,7 @@ static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) /* Ensure that macros cannot overflow jent_loop_shuffle() */ BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63); uint64_t acc_loop_cnt = - jent_loop_shuffle(MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); + jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); if (NULL == ec || NULL == ec->mem) return; @@ -221,8 +244,8 @@ static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) * timing, so we can now benefit from the Central Limit Theorem! */ for (i = 0; i < sizeof(prngState); i++) { - jent_get_nstime_internal(ec, &time_delta); - prngState.b[i] ^= (uint8_t)(time_delta & 0xff); + jent_get_nstime_internal(ec, &time_now); + prngState.b[i] ^= (uint8_t)(time_now & 0xff); } /* @@ -281,7 +304,7 @@ static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) /* Ensure that macros cannot overflow jent_loop_shuffle() */ BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63); uint64_t acc_loop_cnt = - jent_loop_shuffle(MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); + jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); if (NULL == ec || NULL == ec->mem) return; @@ -336,7 +359,7 @@ unsigned int jent_measure_jitter(struct rand_data *ec, uint64_t loop_cnt, uint64_t *ret_current_delta) { - uint64_t time_stamp = 0; + uint64_t time_now = 0; uint64_t current_delta = 0; unsigned int stuck; @@ -347,10 +370,10 @@ unsigned int jent_measure_jitter(struct rand_data *ec, * Get time stamp and calculate time delta to previous * invocation to measure the timing variations */ - jent_get_nstime_internal(ec, &time_stamp); - current_delta = jent_delta(ec->prev_time, time_stamp) / + jent_get_nstime_internal(ec, &time_now); + current_delta = jent_delta(ec->prev_time, time_now) / ec->jent_common_timer_gcd; - ec->prev_time = time_stamp; + ec->prev_time = time_now; /* Check whether we have a stuck measurement. */ stuck = jent_stuck(ec, current_delta); @@ -397,12 +420,12 @@ void jent_random_data(struct rand_data *ec) void jent_read_random_block(struct rand_data *ec, char *dst, size_t dst_len) { - uint8_t jent_block[SHA3_256_SIZE_DIGEST]; + uint8_t jent_block[JENT_SHA3_256_SIZE_DIGEST]; - BUILD_BUG_ON(SHA3_256_SIZE_DIGEST != (DATA_SIZE_BITS / 8)); + BUILD_BUG_ON(JENT_SHA3_256_SIZE_DIGEST != (DATA_SIZE_BITS / 8)); /* The final operation automatically re-initializes the ->hash_state */ - sha3_final(ec->hash_state, jent_block); + jent_sha3_final(ec->hash_state, jent_block); if (dst_len) memcpy(dst, jent_block, dst_len); @@ -410,6 +433,6 @@ void jent_read_random_block(struct rand_data *ec, char *dst, size_t dst_len) * Stir the new state with the data from the old state - the digest * of the old data is not considered to have entropy. */ - sha3_update(ec->hash_state, jent_block, sizeof(jent_block)); + jent_sha3_update(ec->hash_state, jent_block, sizeof(jent_block)); jent_memset_secure(jent_block, sizeof(jent_block)); } diff --git a/third_party/jitterentropy/jitterentropy-noise.h b/third_party/jitterentropy/src/jitterentropy-noise.h similarity index 92% rename from third_party/jitterentropy/jitterentropy-noise.h rename to third_party/jitterentropy/src/jitterentropy-noise.h index afe240ce31..3f31a585fc 100644 --- a/third_party/jitterentropy/jitterentropy-noise.h +++ b/third_party/jitterentropy/src/jitterentropy-noise.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -20,7 +20,7 @@ #ifndef JITTERENTROPY_NOISE_H #define JITTERENTROPY_NOISE_H -#include "jitterentropy.h" +#include "jitterentropy-internal.h" #ifdef __cplusplus extern "C" diff --git a/third_party/jitterentropy/jitterentropy-sha3.c b/third_party/jitterentropy/src/jitterentropy-sha3.c similarity index 84% rename from third_party/jitterentropy/jitterentropy-sha3.c rename to third_party/jitterentropy/src/jitterentropy-sha3.c index 50a6cc4b70..53ab3b6327 100644 --- a/third_party/jitterentropy/jitterentropy-sha3.c +++ b/third_party/jitterentropy/src/jitterentropy-sha3.c @@ -1,6 +1,6 @@ /* Jitter RNG: SHA-3 Implementation * - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -19,7 +19,7 @@ */ #include "jitterentropy-sha3.h" -#include "jitterentropy.h" +#include "jitterentropy-internal.h" /*************************************************************************** * Message Digest Implementation @@ -58,7 +58,7 @@ static inline void le64_to_ptr(uint8_t *p, const uint64_t value) /* state[x + y*5] */ #define A(x, y) (x + 5 * y) -static inline void keccakp_theta(uint64_t s[25]) +static inline void jent_keccakp_theta(uint64_t s[25]) { uint64_t C[5], D[5]; @@ -108,7 +108,7 @@ static inline void keccakp_theta(uint64_t s[25]) s[A(4, 4)] ^= D[4]; } -static inline void keccakp_rho(uint64_t s[25]) +static inline void jent_keccakp_rho(uint64_t s[25]) { /* Step 1 */ /* s[A(0, 0)] = s[A(0, 0)]; */ @@ -141,7 +141,7 @@ static inline void keccakp_rho(uint64_t s[25]) s[A(1, 1)] = rol64(s[A(1, 1)], RHO_ROL(23)); } -static inline void keccakp_pi(uint64_t s[25]) +static inline void jent_keccakp_pi(uint64_t s[25]) { uint64_t t = s[A(4, 4)]; @@ -173,7 +173,7 @@ static inline void keccakp_pi(uint64_t s[25]) s[A(4, 0)] = t; } -static inline void keccakp_chi(uint64_t s[25]) +static inline void jent_keccakp_chi(uint64_t s[25]) { uint64_t t0[5], t1[5]; @@ -220,7 +220,7 @@ static inline void keccakp_chi(uint64_t s[25]) s[A(4, 4)] ^= ~t0[4] & t1[4]; } -static const uint64_t keccakp_iota_vals[] = { +static const uint64_t jent_keccakp_iota_vals[] = { 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL, @@ -231,27 +231,27 @@ static const uint64_t keccakp_iota_vals[] = { 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL }; -static inline void keccakp_iota(uint64_t s[25], unsigned int round) +static inline void jent_keccakp_iota(uint64_t s[25], unsigned int round) { - s[0] ^= keccakp_iota_vals[round]; + s[0] ^= jent_keccakp_iota_vals[round]; } -static inline void keccakp_1600(uint64_t s[25]) +static inline void jent_keccakp_1600(uint64_t s[25]) { unsigned int round; for (round = 0; round < 24; round++) { - keccakp_theta(s); - keccakp_rho(s); - keccakp_pi(s); - keccakp_chi(s); - keccakp_iota(s, round); + jent_keccakp_theta(s); + jent_keccakp_rho(s); + jent_keccakp_pi(s); + jent_keccakp_chi(s); + jent_keccakp_iota(s, round); } } /*********************************** SHA-3 ************************************/ -static inline void sha3_init(struct sha_ctx *ctx) +static inline void jent_sha3_init(struct jent_sha_ctx *ctx) { unsigned int i; @@ -260,15 +260,16 @@ static inline void sha3_init(struct sha_ctx *ctx) ctx->msg_len = 0; } -void sha3_256_init(struct sha_ctx *ctx) +void jent_sha3_256_init(struct jent_sha_ctx *ctx) { - sha3_init(ctx); - ctx->r = SHA3_256_SIZE_BLOCK; - ctx->rword = SHA3_256_SIZE_BLOCK / sizeof(uint64_t); - ctx->digestsize = SHA3_256_SIZE_DIGEST; + jent_sha3_init(ctx); + ctx->r = JENT_SHA3_256_SIZE_BLOCK; + ctx->rword = JENT_SHA3_256_SIZE_BLOCK / sizeof(uint64_t); + ctx->digestsize = JENT_SHA3_256_SIZE_DIGEST; } -static inline void sha3_fill_state(struct sha_ctx *ctx, const uint8_t *in) +static inline void jent_sha3_fill_state(struct jent_sha_ctx *ctx, + const uint8_t *in) { unsigned int i; @@ -278,7 +279,7 @@ static inline void sha3_fill_state(struct sha_ctx *ctx, const uint8_t *in) } } -void sha3_update(struct sha_ctx *ctx, const uint8_t *in, size_t inlen) +void jent_sha3_update(struct jent_sha_ctx *ctx, const uint8_t *in, size_t inlen) { size_t partial = ctx->msg_len % ctx->r; @@ -307,21 +308,21 @@ void sha3_update(struct sha_ctx *ctx, const uint8_t *in, size_t inlen) inlen -= todo; in += todo; - sha3_fill_state(ctx, ctx->partial); - keccakp_1600(ctx->state); + jent_sha3_fill_state(ctx, ctx->partial); + jent_keccakp_1600(ctx->state); } /* Perform a transformation of full block-size messages */ for (; inlen >= ctx->r; inlen -= ctx->r, in += ctx->r) { - sha3_fill_state(ctx, in); - keccakp_1600(ctx->state); + jent_sha3_fill_state(ctx, in); + jent_keccakp_1600(ctx->state); } /* If we have data left, copy it into the partial block buffer */ memcpy(ctx->partial, in, inlen); } -void sha3_final(struct sha_ctx *ctx, uint8_t *digest) +void jent_sha3_final(struct jent_sha_ctx *ctx, uint8_t *digest) { size_t partial = ctx->msg_len % ctx->r; unsigned int i; @@ -339,8 +340,8 @@ void sha3_final(struct sha_ctx *ctx, uint8_t *digest) ctx->partial[ctx->r - 1] |= 0x80; /* Final transformation */ - sha3_fill_state(ctx, ctx->partial); - keccakp_1600(ctx->state); + jent_sha3_fill_state(ctx, ctx->partial); + jent_keccakp_1600(ctx->state); /* * Sponge squeeze phase - the digest size is always smaller as the @@ -354,10 +355,10 @@ void sha3_final(struct sha_ctx *ctx, uint8_t *digest) le32_to_ptr(digest, (uint32_t)(ctx->state[i])); memset(ctx->partial, 0, ctx->r); - sha3_init(ctx); + jent_sha3_init(ctx); } -int sha3_tester(void) +int jent_sha3_tester(void) { HASH_CTX_ON_STACK(ctx); static const uint8_t msg_256[] = { 0x5E, 0x5E, 0xD6 }; @@ -367,14 +368,14 @@ int sha3_tester(void) 0x43, 0x86, 0x8C, 0xC4, 0x0E, 0xC5, 0x5E, 0x00, 0xBB, 0xBB, 0xBD, 0xF5, 0x91, 0x1E }; - uint8_t act[SHA3_256_SIZE_DIGEST] = { 0 }; + uint8_t act[JENT_SHA3_256_SIZE_DIGEST] = { 0 }; unsigned int i; - sha3_256_init(&ctx); - sha3_update(&ctx, msg_256, 3); - sha3_final(&ctx, act); + jent_sha3_256_init(&ctx); + jent_sha3_update(&ctx, msg_256, 3); + jent_sha3_final(&ctx, act); - for (i = 0; i < SHA3_256_SIZE_DIGEST; i++) { + for (i = 0; i < JENT_SHA3_256_SIZE_DIGEST; i++) { if (exp_256[i] != act[i]) return 1; } @@ -382,11 +383,11 @@ int sha3_tester(void) return 0; } -int sha3_alloc(void **hash_state) +int jent_sha3_alloc(void **hash_state) { struct sha_ctx *tmp; - tmp = jent_zalloc(SHA_MAX_CTX_SIZE); + tmp = jent_zalloc(JENT_SHA_MAX_CTX_SIZE); if (!tmp) return 1; @@ -395,9 +396,9 @@ int sha3_alloc(void **hash_state) return 0; } -void sha3_dealloc(void *hash_state) +void jent_sha3_dealloc(void *hash_state) { struct sha_ctx *ctx = (struct sha_ctx *)hash_state; - jent_zfree(ctx, SHA_MAX_CTX_SIZE); + jent_zfree(ctx, JENT_SHA_MAX_CTX_SIZE); } diff --git a/third_party/jitterentropy/jitterentropy-sha3.h b/third_party/jitterentropy/src/jitterentropy-sha3.h similarity index 58% rename from third_party/jitterentropy/jitterentropy-sha3.h rename to third_party/jitterentropy/src/jitterentropy-sha3.h index 565daffb96..c0a3770200 100644 --- a/third_party/jitterentropy/jitterentropy-sha3.h +++ b/third_party/jitterentropy/src/jitterentropy-sha3.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -20,36 +20,38 @@ #ifndef JITTERENTROPY_SHA3_H #define JITTERENTROPY_SHA3_H -#include "jitterentropy.h" +#include "jitterentropy-internal.h" #ifdef __cplusplus extern "C" { #endif -#define SHA3_SIZE_BLOCK(bits) ((1600 - 2 * bits) >> 3) -#define SHA3_256_SIZE_BLOCK SHA3_SIZE_BLOCK(SHA3_256_SIZE_DIGEST_BITS) -#define SHA3_MAX_SIZE_BLOCK SHA3_256_SIZE_BLOCK +#define JENT_SHA3_SIZE_BLOCK(bits) ((1600 - 2 * bits) >> 3) +#define JENT_SHA3_256_SIZE_BLOCK \ + JENT_SHA3_SIZE_BLOCK(JENT_SHA3_256_SIZE_DIGEST_BITS) +#define JENT_SHA3_MAX_SIZE_BLOCK JENT_SHA3_256_SIZE_BLOCK -struct sha_ctx { +struct jent_sha_ctx { uint64_t state[25]; size_t msg_len; unsigned int r; unsigned int rword; unsigned int digestsize; - uint8_t partial[SHA3_MAX_SIZE_BLOCK]; + uint8_t partial[JENT_SHA3_MAX_SIZE_BLOCK]; }; -#define SHA_MAX_CTX_SIZE (sizeof(struct sha_ctx)) +#define JENT_SHA_MAX_CTX_SIZE (sizeof(struct jent_sha_ctx)) #define HASH_CTX_ON_STACK(name) \ - struct sha_ctx name - -void sha3_256_init(struct sha_ctx *ctx); -void sha3_update(struct sha_ctx *ctx, const uint8_t *in, size_t inlen); -void sha3_final(struct sha_ctx *ctx, uint8_t *digest); -int sha3_alloc(void **hash_state); -void sha3_dealloc(void *hash_state); -int sha3_tester(void); + struct jent_sha_ctx name + +void jent_sha3_256_init(struct jent_sha_ctx *ctx); +void jent_sha3_update(struct jent_sha_ctx *ctx, const uint8_t *in, + size_t inlen); +void jent_sha3_final(struct jent_sha_ctx *ctx, uint8_t *digest); +int jent_sha3_alloc(void **hash_state); +void jent_sha3_dealloc(void *hash_state); +int jent_sha3_tester(void); #ifdef __cplusplus } diff --git a/third_party/jitterentropy/jitterentropy-timer.c b/third_party/jitterentropy/src/jitterentropy-timer.c similarity index 98% rename from third_party/jitterentropy/jitterentropy-timer.c rename to third_party/jitterentropy/src/jitterentropy-timer.c index d6fb0859e6..a196f0f644 100644 --- a/third_party/jitterentropy/jitterentropy-timer.c +++ b/third_party/jitterentropy/src/jitterentropy-timer.c @@ -1,6 +1,6 @@ /* Jitter RNG: Internal timer implementation * - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * diff --git a/third_party/jitterentropy/jitterentropy-timer.h b/third_party/jitterentropy/src/jitterentropy-timer.h similarity index 96% rename from third_party/jitterentropy/jitterentropy-timer.h rename to third_party/jitterentropy/src/jitterentropy-timer.h index 6b6ae91754..947eeb07d9 100644 --- a/third_party/jitterentropy/jitterentropy-timer.h +++ b/third_party/jitterentropy/src/jitterentropy-timer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - 2022, Stephan Mueller + * Copyright (C) 2021 - 2024, Stephan Mueller * * License: see LICENSE file in root directory * @@ -20,7 +20,7 @@ #ifndef JITTERENTROPY_TIMER_H #define JITTERENTROPY_TIMER_H -#include "jitterentropy.h" +#include "jitterentropy-internal.h" #ifdef __cplusplus extern "C" diff --git a/third_party/jitterentropy/tests/README.md b/third_party/jitterentropy/tests/README.md new file mode 100644 index 0000000000..7e722701ac --- /dev/null +++ b/third_party/jitterentropy/tests/README.md @@ -0,0 +1,10 @@ +# Jitter RNG Tests + +The following Jitter RNG tests are available in the following +directories: + +* `raw-entropy`: Gathering of the raw unprocessed entropy data and restart test + entropy data required for the SP800-90B analysis + +# Author +Stephan Mueller diff --git a/third_party/jitterentropy/tests/gcd/CMakeLists.txt b/third_party/jitterentropy/tests/gcd/CMakeLists.txt new file mode 100644 index 0000000000..9a841922f6 --- /dev/null +++ b/third_party/jitterentropy/tests/gcd/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(gcd gcd.c) +target_include_directories(gcd PRIVATE ../../src) +target_link_libraries(gcd ${PROJECT_NAME}) diff --git a/third_party/jitterentropy/tests/gcd/Makefile b/third_party/jitterentropy/tests/gcd/Makefile new file mode 100644 index 0000000000..2ab8ab1e0e --- /dev/null +++ b/third_party/jitterentropy/tests/gcd/Makefile @@ -0,0 +1,194 @@ +# +# Copyright (C) 2021 - 2024, Stephan Mueller +# + +CC ?= gcc +CFLAGS += -Wextra -Wall -pedantic -fPIC -O2 -std=gnu18 +#Hardening +CFLAGS += -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fwrapv --param ssp-buffer-size=4 -fvisibility=hidden -fPIE -Wconversion -Wcast-align -Wmissing-field-initializers -Wshadow -Wswitch-enum + +#Optimizations +CFLAGS += -flto +LDFLAGS += -flto + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) +LDFLAGS += -Wl,-z,relro,-z,now,--as-needed -pie +endif + +NAME := gcd + +DESTDIR := +ETCDIR := /etc +BINDIR := /bin +SBINDIR := /sbin +SHAREDIR := /usr/share/keyutils +MANDIR := /usr/share/man +MAN1 := $(MANDIR)/man1 +MAN3 := $(MANDIR)/man3 +MAN5 := $(MANDIR)/man5 +MAN7 := $(MANDIR)/man7 +MAN8 := $(MANDIR)/man8 +INCLUDEDIR := /usr/include +LN := ln +LNS := $(LN) -sf +STRIP ?= strip -s + +############################################################################### +# +# Define compilation options +# +############################################################################### +INCLUDE_DIRS := ../../ ../../src +LIBRARY_DIRS := +LIBRARIES := + +CFLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(LIBRARIES),-l$(library)) + +############################################################################### +# +# Get version name and cross check +# +############################################################################### +VERFILE := gcd.c + +APPMAJOR := $(shell grep '^\#define.*MAJVERSION' $(VERFILE) | awk '{print $$3}') +APPMINOR := $(shell grep '^\#define.*MINVERSION' $(VERFILE) | awk '{print $$3}') +APPPATCH := $(shell grep '^\#define.*PATCHLEVEL' $(VERFILE) | awk '{print $$3}') +APPVERSION := $(APPMAJOR).$(APPMINOR).$(APPPATCH) + +############################################################################### +# +# Guess at the appropriate lib directory and word size +# +############################################################################### +ifeq ($(UNAME_S),Linux) + +ifeq ($(origin LIBDIR),undefined) +LIBDIR := $(shell ldd /usr/bin/make | grep '\(/libc\.\)' | sed -e 's!.*\(/.*\)/libc[.].*!\1!') +endif +ifeq ($(origin USRLIBDIR),undefined) +USRLIBDIR := $(patsubst /lib/%,/usr/lib/%,$(LIBDIR)) +endif +BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit + +ifeq ($(origin CFLAGS),undefined) +ifeq ($(BUILDFOR),32-bit) +CFLAGS += -m32 +LIBDIR := /lib +USRLIBDIR := /usr/lib +else +ifeq ($(BUILDFOR),64-bit) +CFLAGS += -m64 +LIBDIR := /lib64 +USRLIBDIR := /usr/lib64 +endif +endif +endif + +else +LIBDIR := /lib +USRLIBDIR := /usr/lib +endif + + +############################################################################### +# +# Define files to be compiled +# +############################################################################### +C_SRCS := $(wildcard *.c) ../../src/jitterentropy-gcd.c +C_OBJS := ${C_SRCS:.c=.o} +C_GCOV := ${C_SRCS:.c=.gcda} +C_GCOV += ${C_SRCS:.c=.gcno} +C_GCOV += ${C_SRCS:.c=.gcov} +OBJS := $(C_OBJS) + +analyze_srcs = $(filter %.c, $(sort $(C_SRCS))) +analyze_plists = $(analyze_srcs:%.c=%.plist) + +.PHONY: all scan install clean cppcheck distclean debug asanaddress asanthread leak gcov + +all: $(NAME) + +debug: CFLAGS += -g -DDEBUG +debug: DBG-$(NAME) + +asanaddress: CFLAGS += -g -DDEBUG -fsanitize=address -fno-omit-frame-pointer +asanaddress: LDFLAGS += -fsanitize=address +asanaddress: DBG-$(NAME) + +asanthread: CFLAGS += -g -DDEBUG -fsanitize=thread -fno-omit-frame-pointer +asanthread: LDFLAGS += -fsanitize=thread +asanthread: DBG-$(NAME) + +leak: CFLAGS += -g -DDEBUG -fsanitize=leak -fno-omit-frame-pointer +leak: LDFLAGS += -fsanitize=leak +leak: DBG-$(NAME) + +# Compile for the use of GCOV +# Usage after compilation: gcov .c +gcov: CFLAGS += -g -DDEBUG -fprofile-arcs -ftest-coverage +gcov: LDFLAGS += -fprofile-arcs +gcov: DBG-$(NAME) + +############################################################################### +# +# Build the library +# +############################################################################## + +$(NAME): $(OBJS) + $(CC) -o $(NAME) $(OBJS) $(LDFLAGS) + $(STRIP) $(NAME) + +DBG-$(NAME): $(OBJS) + $(CC) -g -DDEBUG -o $(NAME) $(OBJS) $(LDFLAGS) + +$(analyze_plists): %.plist: %.c + @echo " CCSA " $@ + clang --analyze $(CFLAGS) $< -o $@ + +scan: $(analyze_plists) + +cppcheck: + cppcheck --force -q --enable=performance --enable=warning --enable=portability *.h *.c ../lib/*.c ../lib/*.h + +asm: + $(foreach b, $(C_SRCS), $(CC) $(CFLAGS) -S -fverbose-asm -o ${b:.c=.s} $(b);) + +install: + install -m 0755 $(NAME) -D -t $(DESTDIR)$(BINDIR)/ + +############################################################################### +# +# Clean +# +############################################################################### + +clean: + @- $(RM) $(OBJS) + @- $(RM) $(NAME) + @- $(RM) $(C_GCOV) + @- $(RM) *.gcov + @- $(RM) $(analyze_plists) + +distclean: clean + +############################################################################### +# +# Show variables +# +############################################################################### +show_vars: + @echo APPVERSION=$(APPVERSION) + @echo DESTDIR=$(DESTDIR) + @echo BINDIR=$(BINDIR) + @echo LIBDIR=$(LIBDIR) + @echo USRLIBDIR=$(USRLIBDIR) + @echo BUILDFOR=$(BUILDFOR) + @echo NAME=$(NAME) + @echo LDFLAGS=$(LDFLAGS) + @echo CFLAGS=$(CFLAGS) diff --git a/third_party/jitterentropy/tests/gcd/gcd.c b/third_party/jitterentropy/tests/gcd/gcd.c new file mode 100644 index 0000000000..94c82d827a --- /dev/null +++ b/third_party/jitterentropy/tests/gcd/gcd.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 - 2024, Stephan Mueller + * + * License: see LICENSE file in root directory + * + * 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 +#include +#include + +#include "jitterentropy-gcd.h" + +#define MAJVERSION 0 /* 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. */ + +#define ELEM 1000 +#define EXP_GCD 50ULL +int main(int argc, char *argv[]) +{ + uint64_t *gcd = jent_gcd_init(ELEM); + uint64_t val; + unsigned int i; + + (void)argc; + (void)argv; + + for (i = 0; i < ELEM; i++) + jent_gcd_add_value(gcd, i * EXP_GCD, i); + + if (jent_gcd_analyze(gcd, ELEM)) + return 1; + + jent_gcd_fini(gcd, ELEM); + + if (jent_gcd_get(&val)) + return 2; + + if (val != EXP_GCD) + return 3; + + return 0; +}