From a69fd1da62e55621e6db0580370e66214c6132a9 Mon Sep 17 00:00:00 2001 From: K1 Date: Thu, 26 Oct 2023 17:41:21 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E6=95=B0=E7=86=B5=E6=BA=90?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=B3=BB=E7=BB=9F=E6=97=B6=E9=97=B4(RTC)?= =?UTF-8?q?=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 通过反复获取系统时间(real-time clock)来产生不可预测的数据。 算法依赖于在执行代码或读写内存时,受缓存未命中、系统中断、调度等多个 因素影响,导致消耗的时间不确定,从而每次获取的系统时间也不确定。 具体包括2个方案: 1.执行特定代码后,获取系统时间。 2.读写特定内存后,获取系统时间。 --- .github/workflows/ci.yml | 2 +- CHANGES | 2 + Configure | 2 +- crypto/info.c | 3 + .../implementations/rands/seeding/rand_unix.c | 73 +++++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7cb3064c..e9b6af681 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,7 +185,7 @@ jobs: - name: modprobe tls run: sudo modprobe tls - name: config - run: ./config --banner=Configured --strict-warnings no-ec enable-ssl-trace enable-zlib enable-zlib-dynamic enable-crypto-mdebug enable-crypto-mdebug-backtrace enable-egd enable-ktls enable-fips enable-ntls enable-optimize-chacha-choose enable-status enable-crypto-mdebug-count enable-cert-compression enable-delegated-credential enable-bn-method && perl configdata.pm --dump + run: ./config --banner=Configured --strict-warnings no-ec enable-ssl-trace enable-zlib enable-zlib-dynamic enable-crypto-mdebug enable-crypto-mdebug-backtrace enable-egd enable-ktls enable-fips enable-ntls enable-optimize-chacha-choose enable-status enable-crypto-mdebug-count enable-cert-compression enable-delegated-credential enable-bn-method --with-rand-seed=getrandom,rtc && perl configdata.pm --dump - name: make run: make -s -j4 - name: make test diff --git a/CHANGES b/CHANGES index 6aa6d1f59..d6079fe1d 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ Changes between 8.4.0 and 8.5.0 [xx XXX xxxx] + *) 随机数熵源增加系统时间(RTC)方案 + *) 增加商用密码检测和认证Provider,包括身份认证、完整性验证、算法自测试、随机数自检、 熵源健康测试;增加mod应用,包括生成SMTC配置、自测试功能 diff --git a/Configure b/Configure index 2067a6680..40eebb90b 100755 --- a/Configure +++ b/Configure @@ -793,7 +793,7 @@ my %cmdvars = (); # Stores FOO='blah' type arguments my %unsupported_options = (); my %deprecated_options = (); # If you change this, update apps/version.c -my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom); +my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom rtc); my @seed_sources = (); while (@argvcopy) { diff --git a/crypto/info.c b/crypto/info.c index 5c6b4983f..69142d396 100644 --- a/crypto/info.c +++ b/crypto/info.c @@ -151,6 +151,9 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) #endif #ifdef OPENSSL_RAND_SEED_OS add_seeds_string("os-specific"); +#endif +#ifdef OPENSSL_RAND_SEED_RTC + add_seeds_string("real-time-clock"); #endif seed_sources = seeds; } diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index fede8441d..6fb13195a 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -48,6 +48,7 @@ # include # include # include +# include static uint64_t get_time_stamp(void); static uint64_t get_timer_bits(void); @@ -101,6 +102,7 @@ static uint64_t get_timer_bits(void); # undef OPENSSL_RAND_SEED_RDTSC # undef OPENSSL_RAND_SEED_RDCPU # undef OPENSSL_RAND_SEED_EGD +# undef OPENSSL_RAND_SEED_RTC #endif #if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE) @@ -604,6 +606,67 @@ void ossl_rand_pool_keep_random_devices_open(int keep) # endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */ +# if defined(OPENSSL_RAND_SEED_RTC) +static size_t ossl_prov_acquire_entropy_from_rtc1(RAND_POOL *pool) +{ + size_t i, k, bytes_needed; + struct timespec ts; + unsigned char v; + + bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/); + + for (i = 0; i < bytes_needed; i++) { + /* + * burn some cpu; hope for interrupts, cache collisions, bus + * interference, etc. + */ + for (k = 0; k < 99; k++) + ts.tv_nsec = random(); + + /* sleep for 1/65536 of a second (15 us). */ + ts.tv_sec = 0; + ts.tv_nsec = 15000; + nanosleep(&ts, NULL); + + /* Get wall clock time, take 8 bits. */ + clock_gettime(CLOCK_REALTIME, &ts); + v = (unsigned char)(ts.tv_nsec & 0xFF); + ossl_rand_pool_add(pool, &v, sizeof(v), 2); + } + return ossl_rand_pool_entropy_available(pool); +} + +static size_t ossl_prov_acquire_entropy_from_rtc2(RAND_POOL *pool) +{ + size_t i, k, bytes_needed; + struct timespec ts; + unsigned char v; + + bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/); + + for (i = 0; i < bytes_needed; i++) { + long buf[100]; + /* + * burn some cpu; hope for interrupts, cache collisions, bus + * interference, etc. + */ + for (k = 1; k < OSSL_NELEM(buf); k++) + buf[k] = buf[k-1] ^ random(); + + /* sleep for 1/65536 of a second (15 us). */ + ts.tv_sec = 0; + ts.tv_nsec = 15000; + nanosleep(&ts, NULL); + + /* Get wall clock time, take 8 bits. */ + clock_gettime(CLOCK_REALTIME, &ts); + v = (unsigned char)(ts.tv_nsec & 0xFF); + ossl_rand_pool_add(pool, &v, sizeof(v), 2); + } + return ossl_rand_pool_entropy_available(pool); +} +# endif + /* * Try the various seeding methods in turn, exit when successful. * @@ -741,6 +804,16 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) } # endif +# if defined(OPENSSL_RAND_SEED_RTC) + entropy_available = ossl_prov_acquire_entropy_from_rtc1(pool); + if (entropy_available > 0) + return entropy_available; + + entropy_available = ossl_prov_acquire_entropy_from_rtc2(pool); + if (entropy_available > 0) + return entropy_available; +# endif + return ossl_rand_pool_entropy_available(pool); # endif }