A local copy of OpenSSL from GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

882 lines
26 KiB

Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
DRBG: fix reseeding via RAND_add()/RAND_seed() with large input In pull request #4328 the seeding of the DRBG via RAND_add()/RAND_seed() was implemented by buffering the data in a random pool where it is picked up later by the rand_drbg_get_entropy() callback. This buffer was limited to the size of 4096 bytes. When a larger input was added via RAND_add() or RAND_seed() to the DRBG, the reseeding failed, but the error returned by the DRBG was ignored by the two calling functions, which both don't return an error code. As a consequence, the data provided by the application was effectively ignored. This commit fixes the problem by a more efficient implementation which does not copy the data in memory and by raising the buffer the size limit to INT32_MAX (2 gigabytes). This is less than the NIST limit of 2^35 bits but it was chosen intentionally to avoid platform dependent problems like integer sizes and/or signed/unsigned conversion. Additionally, the DRBG is now less permissive on errors: In addition to pushing a message to the openssl error stack, it enters the error state, which forces a reinstantiation on next call. Thanks go to Dr. Falko Strenzke for reporting this issue to the openssl-security mailing list. After internal discussion the issue has been categorized as not being security relevant, because the DRBG reseeds automatically and is fully functional even without additional randomness provided by the application. Fixes #7381 Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/7382)
3 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
rand_unix.c: open random devices on first use only Commit c7504aeb640a (pr #6432) fixed a regression for applications in chroot environments, which compensated the fact that the new OpenSSL CSPRNG (based on the NIST DRBG) now reseeds periodically, which the previous one didn't. Now the reseeding could fail in the chroot environment if the DEVRANDOM devices were not present anymore and no other entropy source (e.g. getrandom()) was available. The solution was to keep the file handles for the DEVRANDOM devices open by default. In fact, the fix did more than this, it opened the DEVRANDOM devices early and unconditionally in rand_pool_init(), which had the unwanted side effect that the devices were opened (and kept open) even in cases when they were not used at all, for example when the getrandom() system call was available. Due to a bug (issue #7419) this even happened when the feature was disabled by the application. This commit removes the unconditional opening of all DEVRANDOM devices. They will now only be opened (and kept open) on first use. In particular, if getrandom() is available, the handles will not be opened unnecessarily. This change does not introduce a regression for applications compiled for libcrypto 1.1.0, because the SSLEAY RNG also seeds on first use. So in the above constellation the CSPRNG will only be properly seeded if it is happens before the forking and chrooting. Fixes #7419 Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/7437)
3 years ago
rand_unix.c: open random devices on first use only Commit c7504aeb640a (pr #6432) fixed a regression for applications in chroot environments, which compensated the fact that the new OpenSSL CSPRNG (based on the NIST DRBG) now reseeds periodically, which the previous one didn't. Now the reseeding could fail in the chroot environment if the DEVRANDOM devices were not present anymore and no other entropy source (e.g. getrandom()) was available. The solution was to keep the file handles for the DEVRANDOM devices open by default. In fact, the fix did more than this, it opened the DEVRANDOM devices early and unconditionally in rand_pool_init(), which had the unwanted side effect that the devices were opened (and kept open) even in cases when they were not used at all, for example when the getrandom() system call was available. Due to a bug (issue #7419) this even happened when the feature was disabled by the application. This commit removes the unconditional opening of all DEVRANDOM devices. They will now only be opened (and kept open) on first use. In particular, if getrandom() is available, the handles will not be opened unnecessarily. This change does not introduce a regression for applications compiled for libcrypto 1.1.0, because the SSLEAY RNG also seeds on first use. So in the above constellation the CSPRNG will only be properly seeded if it is happens before the forking and chrooting. Fixes #7419 Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/7437)
3 years ago
rand_unix.c: open random devices on first use only Commit c7504aeb640a (pr #6432) fixed a regression for applications in chroot environments, which compensated the fact that the new OpenSSL CSPRNG (based on the NIST DRBG) now reseeds periodically, which the previous one didn't. Now the reseeding could fail in the chroot environment if the DEVRANDOM devices were not present anymore and no other entropy source (e.g. getrandom()) was available. The solution was to keep the file handles for the DEVRANDOM devices open by default. In fact, the fix did more than this, it opened the DEVRANDOM devices early and unconditionally in rand_pool_init(), which had the unwanted side effect that the devices were opened (and kept open) even in cases when they were not used at all, for example when the getrandom() system call was available. Due to a bug (issue #7419) this even happened when the feature was disabled by the application. This commit removes the unconditional opening of all DEVRANDOM devices. They will now only be opened (and kept open) on first use. In particular, if getrandom() is available, the handles will not be opened unnecessarily. This change does not introduce a regression for applications compiled for libcrypto 1.1.0, because the SSLEAY RNG also seeds on first use. So in the above constellation the CSPRNG will only be properly seeded if it is happens before the forking and chrooting. Fixes #7419 Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/7437)
3 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Start up DEVRANDOM entropy improvement for older Linux devices. Improve handling of low entropy at start up from /dev/urandom by waiting for a read(2) call on /dev/random to succeed. Once one such call has succeeded, a shared memory segment is created and persisted as an indicator to other processes that /dev/urandom is properly seeded. This does not fully prevent against attacks weakening the entropy source. An attacker who has control of the machine early in its boot sequence could create the shared memory segment preventing detection of low entropy conditions. However, this is no worse than the current situation. An attacker would also be capable of removing the shared memory segment and causing seeding to reoccur resulting in a denial of service attack. This is partially mitigated by keeping the shared memory alive for the duration of the process's existence. Thus, an attacker would not only need to have called call shmctl(2) with the IPC_RMID command but the system must subsequently enter a state where no instances of libcrypto exist in any process. Even one long running process will prevent this attack. The System V shared memory calls used here go back at least as far as Linux kernel 2.0. Linux kernels 4.8 and later, don't have a reliable way to detect that /dev/urandom has been properly seeded, so a failure is raised for this case (i.e. the getentropy(2) call has already failed). Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/9595)
2 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
Fix reseeding issues of the public RAND_DRBG Reseeding is handled very differently by the classic RAND_METHOD API and the new RAND_DRBG api. These differences led to some problems when the new RAND_DRBG was made the default OpenSSL RNG. In particular, RAND_add() did not work as expected anymore. These issues are discussed on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API' and in Pull Request #4328. This commit fixes the mentioned issues, introducing the following changes: - Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which facilitates collecting entropy by the get_entropy() callback. - Don't use RAND_poll()/RAND_add() for collecting entropy from the get_entropy() callback anymore. Instead, replace RAND_poll() by RAND_POOL_acquire_entropy(). - Add a new function rand_drbg_restart() which tries to get the DRBG in an instantiated state by all means, regardless of the current state (uninstantiated, error, ...) the DRBG is in. If the caller provides entropy or additional input, it will be used for reseeding. - Restore the original documented behaviour of RAND_add() and RAND_poll() (namely to reseed the DRBG immediately) by a new implementation based on rand_drbg_restart(). - Add automatic error recovery from temporary failures of the entropy source to RAND_DRBG_generate() using the rand_drbg_restart() function. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4328)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
DRBG: implement a get_nonce() callback Fixes #5849 In pull request #5503 a fallback was added which adds a random nonce of security_strength/2 bits if no nonce callback is provided. This change raised the entropy requirements form 256 to 384 bit, which can cause problems on some platforms (e.g. VMS, see issue #5849). The requirements for the nonce are given in section 8.6.7 of NIST SP 800-90Ar1: A nonce may be required in the construction of a seed during instantiation in order to provide a security cushion to block certain attacks. The nonce shall be either: a) A value with at least (security_strength/2) bits of entropy, or b) A value that is expected to repeat no more often than a (security_strength/2)-bit random string would be expected to repeat. Each nonce shall be unique to the cryptographic module in which instantiation is performed, but need not be secret. When used, the nonce shall be considered to be a critical security parameter. This commit implements a nonce of type b) in order to lower the entropy requirements during instantiation back to 256 bits. The formulation "shall be unique to the cryptographic module" above implies that the nonce needs to be unique among (with high probability) among all DRBG instances in "space" and "time". We try to achieve this goal by creating a nonce of the following form nonce = app-specific-data || high-resolution-utc-timestamp || counter Where || denotes concatenation. The application specific data can be something like the process or group id of the application. A utc timestamp is used because it increases monotonically, provided the system time is synchronized. This approach may not be perfect yet for a FIPS evaluation, but it should be good enough for the moment. This commit also harmonizes the implementation of the get_nonce() and the get_additional_data() callbacks and moves the platform specific parts from rand_lib.c into rand_unix.c, rand_win.c, and rand_vms.c. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5920)
4 years ago
  1. /*
  2. * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #ifndef _GNU_SOURCE
  10. # define _GNU_SOURCE
  11. #endif
  12. #include "../e_os.h"
  13. #include <stdio.h>
  14. #include "internal/cryptlib.h"
  15. #include <openssl/rand.h>
  16. #include <openssl/crypto.h>
  17. #include "crypto/rand_pool.h"
  18. #include "crypto/rand.h"
  19. #include <stdio.h>
  20. #include "internal/dso.h"
  21. #include "prov/seeding.h"
  22. #ifdef __linux
  23. # include <sys/syscall.h>
  24. # ifdef DEVRANDOM_WAIT
  25. # include <sys/shm.h>
  26. # include <sys/utsname.h>
  27. # endif
  28. #endif
  29. #if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(OPENSSL_SYS_UEFI)
  30. # include <sys/types.h>
  31. # include <sys/sysctl.h>
  32. # include <sys/param.h>
  33. #endif
  34. #if defined(__OpenBSD__)
  35. # include <sys/param.h>
  36. #endif
  37. #if defined(__DragonFly__)
  38. # include <sys/param.h>
  39. # include <sys/random.h>
  40. #endif
  41. #if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
  42. || defined(__DJGPP__)
  43. # include <sys/types.h>
  44. # include <sys/stat.h>
  45. # include <fcntl.h>
  46. # include <unistd.h>
  47. # include <sys/time.h>
  48. static uint64_t get_time_stamp(void);
  49. static uint64_t get_timer_bits(void);
  50. /* Macro to convert two thirty two bit values into a sixty four bit one */
  51. # define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
  52. /*
  53. * Check for the existence and support of POSIX timers. The standard
  54. * says that the _POSIX_TIMERS macro will have a positive value if they
  55. * are available.
  56. *
  57. * However, we want an additional constraint: that the timer support does
  58. * not require an extra library dependency. Early versions of glibc
  59. * require -lrt to be specified on the link line to access the timers,
  60. * so this needs to be checked for.
  61. *
  62. * It is worse because some libraries define __GLIBC__ but don't
  63. * support the version testing macro (e.g. uClibc). This means
  64. * an extra check is needed.
  65. *
  66. * The final condition is:
  67. * "have posix timers and either not glibc or glibc without -lrt"
  68. *
  69. * The nested #if sequences are required to avoid using a parameterised
  70. * macro that might be undefined.
  71. */
  72. # undef OSSL_POSIX_TIMER_OKAY
  73. /* On some systems, _POSIX_TIMERS is defined but empty.
  74. * Subtracting by 0 when comparing avoids an error in this case. */
  75. # if defined(_POSIX_TIMERS) && _POSIX_TIMERS -0 > 0
  76. # if defined(__GLIBC__)
  77. # if defined(__GLIBC_PREREQ)
  78. # if __GLIBC_PREREQ(2, 17)
  79. # define OSSL_POSIX_TIMER_OKAY
  80. # endif
  81. # endif
  82. # else
  83. # define OSSL_POSIX_TIMER_OKAY
  84. # endif
  85. # endif
  86. #endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
  87. || defined(__DJGPP__) */
  88. #if defined(OPENSSL_RAND_SEED_NONE)
  89. /* none means none. this simplifies the following logic */
  90. # undef OPENSSL_RAND_SEED_OS
  91. # undef OPENSSL_RAND_SEED_GETRANDOM
  92. # undef OPENSSL_RAND_SEED_LIBRANDOM
  93. # undef OPENSSL_RAND_SEED_DEVRANDOM
  94. # undef OPENSSL_RAND_SEED_RDTSC
  95. # undef OPENSSL_RAND_SEED_RDCPU
  96. # undef OPENSSL_RAND_SEED_EGD
  97. #endif
  98. #if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE)
  99. # error "UEFI only supports seeding NONE"
  100. #endif
  101. #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
  102. || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
  103. || defined(OPENSSL_SYS_UEFI))
  104. # if defined(OPENSSL_SYS_VOS)
  105. # ifndef OPENSSL_RAND_SEED_OS
  106. # error "Unsupported seeding method configured; must be os"
  107. # endif
  108. # if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
  109. # error "Unsupported HP-PA and IA32 at the same time."
  110. # endif
  111. # if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
  112. # error "Must have one of HP-PA or IA32"
  113. # endif
  114. /*
  115. * The following algorithm repeatedly samples the real-time clock (RTC) to
  116. * generate a sequence of unpredictable data. The algorithm relies upon the
  117. * uneven execution speed of the code (due to factors such as cache misses,
  118. * interrupts, bus activity, and scheduling) and upon the rather large
  119. * relative difference between the speed of the clock and the rate at which
  120. * it can be read. If it is ported to an environment where execution speed
  121. * is more constant or where the RTC ticks at a much slower rate, or the
  122. * clock can be read with fewer instructions, it is likely that the results
  123. * would be far more predictable. This should only be used for legacy
  124. * platforms.
  125. *
  126. * As a precaution, we assume only 2 bits of entropy per byte.
  127. */
  128. size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
  129. {
  130. short int code;
  131. int i, k;
  132. size_t bytes_needed;
  133. struct timespec ts;
  134. unsigned char v;
  135. # ifdef OPENSSL_SYS_VOS_HPPA
  136. long duration;
  137. extern void s$sleep(long *_duration, short int *_code);
  138. # else
  139. long long duration;
  140. extern void s$sleep2(long long *_duration, short int *_code);
  141. # endif
  142. bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
  143. for (i = 0; i < bytes_needed; i++) {
  144. /*
  145. * burn some cpu; hope for interrupts, cache collisions, bus
  146. * interference, etc.
  147. */
  148. for (k = 0; k < 99; k++)
  149. ts.tv_nsec = random();
  150. # ifdef OPENSSL_SYS_VOS_HPPA
  151. /* sleep for 1/1024 of a second (976 us). */
  152. duration = 1;
  153. s$sleep(&duration, &code);
  154. # else
  155. /* sleep for 1/65536 of a second (15 us). */
  156. duration = 1;
  157. s$sleep2(&duration, &code);
  158. # endif
  159. /* Get wall clock time, take 8 bits. */
  160. clock_gettime(CLOCK_REALTIME, &ts);
  161. v = (unsigned char)(ts.tv_nsec & 0xFF);
  162. ossl_rand_pool_add(pool, arg, &v, sizeof(v) , 2);
  163. }
  164. return ossl_rand_pool_entropy_available(pool);
  165. }
  166. void ossl_rand_pool_cleanup(void)
  167. {
  168. }
  169. void ossl_rand_pool_keep_random_devices_open(int keep)
  170. {
  171. }
  172. # else
  173. # if defined(OPENSSL_RAND_SEED_EGD) && \
  174. (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
  175. # error "Seeding uses EGD but EGD is turned off or no device given"
  176. # endif
  177. # if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
  178. # error "Seeding uses urandom but DEVRANDOM is not configured"
  179. # endif
  180. # if defined(OPENSSL_RAND_SEED_OS)
  181. # if !defined(DEVRANDOM)
  182. # error "OS seeding requires DEVRANDOM to be configured"
  183. # endif
  184. # define OPENSSL_RAND_SEED_GETRANDOM
  185. # define OPENSSL_RAND_SEED_DEVRANDOM
  186. # endif
  187. # if defined(OPENSSL_RAND_SEED_LIBRANDOM)
  188. # error "librandom not (yet) supported"
  189. # endif
  190. # if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
  191. /*
  192. * sysctl_random(): Use sysctl() to read a random number from the kernel
  193. * Returns the number of bytes returned in buf on success, -1 on failure.
  194. */
  195. static ssize_t sysctl_random(char *buf, size_t buflen)
  196. {
  197. int mib[2];
  198. size_t done = 0;
  199. size_t len;
  200. /*
  201. * Note: sign conversion between size_t and ssize_t is safe even
  202. * without a range check, see comment in syscall_random()
  203. */
  204. /*
  205. * On FreeBSD old implementations returned longs, newer versions support
  206. * variable sizes up to 256 byte. The code below would not work properly
  207. * when the sysctl returns long and we want to request something not a
  208. * multiple of longs, which should never be the case.
  209. */
  210. #if defined(__FreeBSD__)
  211. if (!ossl_assert(buflen % sizeof(long) == 0)) {
  212. errno = EINVAL;
  213. return -1;
  214. }
  215. #endif
  216. /*
  217. * On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
  218. * filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
  219. * it returns a variable number of bytes with the current version supporting
  220. * up to 256 bytes.
  221. * Just return an error on older NetBSD versions.
  222. */
  223. #if defined(__NetBSD__) && __NetBSD_Version__ < 400000000
  224. errno = ENOSYS;
  225. return -1;
  226. #endif
  227. mib[0] = CTL_KERN;
  228. mib[1] = KERN_ARND;
  229. do {
  230. len = buflen > 256 ? 256 : buflen;
  231. if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
  232. return done > 0 ? done : -1;
  233. done += len;
  234. buf += len;
  235. buflen -= len;
  236. } while (buflen > 0);
  237. return done;
  238. }
  239. # endif
  240. # if defined(OPENSSL_RAND_SEED_GETRANDOM)
  241. # if defined(__linux) && !defined(__NR_getrandom)
  242. # if defined(__arm__)
  243. # define __NR_getrandom (__NR_SYSCALL_BASE+384)
  244. # elif defined(__i386__)
  245. # define __NR_getrandom 355
  246. # elif defined(__x86_64__)
  247. # if defined(__ILP32__)
  248. # define __NR_getrandom (__X32_SYSCALL_BIT + 318)
  249. # else
  250. # define __NR_getrandom 318
  251. # endif
  252. # elif defined(__xtensa__)
  253. # define __NR_getrandom 338
  254. # elif defined(__s390__) || defined(__s390x__)
  255. # define __NR_getrandom 349
  256. # elif defined(__bfin__)
  257. # define __NR_getrandom 389
  258. # elif defined(__powerpc__)
  259. # define __NR_getrandom 359
  260. # elif defined(__mips__) || defined(__mips64)
  261. # if _MIPS_SIM == _MIPS_SIM_ABI32
  262. # define __NR_getrandom (__NR_Linux + 353)
  263. # elif _MIPS_SIM == _MIPS_SIM_ABI64
  264. # define __NR_getrandom (__NR_Linux + 313)
  265. # elif _MIPS_SIM == _MIPS_SIM_NABI32
  266. # define __NR_getrandom (__NR_Linux + 317)
  267. # endif
  268. # elif defined(__hppa__)
  269. # define __NR_getrandom (__NR_Linux + 339)
  270. # elif defined(__sparc__)
  271. # define __NR_getrandom 347
  272. # elif defined(__ia64__)
  273. # define __NR_getrandom 1339
  274. # elif defined(__alpha__)
  275. # define __NR_getrandom 511
  276. # elif defined(__sh__)
  277. # if defined(__SH5__)
  278. # define __NR_getrandom 373
  279. # else
  280. # define __NR_getrandom 384
  281. # endif
  282. # elif defined(__avr32__)
  283. # define __NR_getrandom 317
  284. # elif defined(__microblaze__)
  285. # define __NR_getrandom 385
  286. # elif defined(__m68k__)
  287. # define __NR_getrandom 352
  288. # elif defined(__cris__)
  289. # define __NR_getrandom 356
  290. # elif defined(__aarch64__)
  291. # define __NR_getrandom 278
  292. # else /* generic */
  293. # define __NR_getrandom 278
  294. # endif
  295. # endif
  296. /*
  297. * syscall_random(): Try to get random data using a system call
  298. * returns the number of bytes returned in buf, or < 0 on error.
  299. */
  300. static ssize_t syscall_random(void *buf, size_t buflen)
  301. {
  302. /*
  303. * Note: 'buflen' equals the size of the buffer which is used by the
  304. * get_entropy() callback of the RAND_DRBG. It is roughly bounded by
  305. *
  306. * 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14
  307. *
  308. * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
  309. * between size_t and ssize_t is safe even without a range check.
  310. */
  311. /*
  312. * Do runtime detection to find getentropy().
  313. *
  314. * Known OSs that should support this:
  315. * - Darwin since 16 (OSX 10.12, IOS 10.0).
  316. * - Solaris since 11.3
  317. * - OpenBSD since 5.6
  318. * - Linux since 3.17 with glibc 2.25
  319. * - FreeBSD since 12.0 (1200061)
  320. *
  321. * Note: Sometimes getentropy() can be provided but not implemented
  322. * internally. So we need to check errno for ENOSYS
  323. */
  324. # if !defined(__DragonFly__) && !defined(__NetBSD__)
  325. # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
  326. extern int getentropy(void *buffer, size_t length) __attribute__((weak));
  327. if (getentropy != NULL) {
  328. if (getentropy(buf, buflen) == 0)
  329. return (ssize_t)buflen;
  330. if (errno != ENOSYS)
  331. return -1;
  332. }
  333. # elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)
  334. if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
  335. return (ssize_t)buflen;
  336. return -1;
  337. # else
  338. union {
  339. void *p;
  340. int (*f)(void *buffer, size_t length);
  341. } p_getentropy;
  342. /*
  343. * We could cache the result of the lookup, but we normally don't
  344. * call this function often.
  345. */
  346. ERR_set_mark();
  347. p_getentropy.p = DSO_global_lookup("getentropy");
  348. ERR_pop_to_mark();
  349. if (p_getentropy.p != NULL)
  350. return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
  351. # endif
  352. # endif /* !__DragonFly__ */
  353. /* Linux supports this since version 3.17 */
  354. # if defined(__linux) && defined(__NR_getrandom)
  355. return syscall(__NR_getrandom, buf, buflen, 0);
  356. # elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
  357. return sysctl_random(buf, buflen);
  358. # elif (defined(__DragonFly__) && __DragonFly_version >= 500700) \
  359. || (defined(__NetBSD__) && __NetBSD_Version >= 1000000000)
  360. return getrandom(buf, buflen, 0);
  361. # else
  362. errno = ENOSYS;
  363. return -1;
  364. # endif
  365. }
  366. # endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
  367. # if defined(OPENSSL_RAND_SEED_DEVRANDOM)
  368. static const char *random_device_paths[] = { DEVRANDOM };
  369. static struct random_device {
  370. int fd;
  371. dev_t dev;
  372. ino_t ino;
  373. mode_t mode;
  374. dev_t rdev;
  375. } random_devices[OSSL_NELEM(random_device_paths)];
  376. static int keep_random_devices_open = 1;
  377. # if defined(__linux) && defined(DEVRANDOM_WAIT) \
  378. && defined(OPENSSL_RAND_SEED_GETRANDOM)
  379. static void *shm_addr;
  380. static void cleanup_shm(void)
  381. {
  382. shmdt(shm_addr);
  383. }
  384. /*
  385. * Ensure that the system randomness source has been adequately seeded.
  386. * This is done by having the first start of libcrypto, wait until the device
  387. * /dev/random becomes able to supply a byte of entropy. Subsequent starts
  388. * of the library and later reseedings do not need to do this.
  389. */
  390. static int wait_random_seeded(void)
  391. {
  392. static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;
  393. static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };
  394. int kernel[2];
  395. int shm_id, fd, r;
  396. char c, *p;
  397. struct utsname un;
  398. fd_set fds;
  399. if (!seeded) {
  400. /* See if anything has created the global seeded indication */
  401. if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {
  402. /*
  403. * Check the kernel's version and fail if it is too recent.
  404. *
  405. * Linux kernels from 4.8 onwards do not guarantee that
  406. * /dev/urandom is properly seeded when /dev/random becomes
  407. * readable. However, such kernels support the getentropy(2)
  408. * system call and this should always succeed which renders
  409. * this alternative but essentially identical source moot.
  410. */
  411. if (uname(&un) == 0) {
  412. kernel[0] = atoi(un.release);
  413. p = strchr(un.release, '.');
  414. kernel[1] = p == NULL ? 0 : atoi(p + 1);
  415. if (kernel[0] > kernel_version[0]
  416. || (kernel[0] == kernel_version[0]
  417. && kernel[1] >= kernel_version[1])) {
  418. return 0;
  419. }
  420. }
  421. /* Open /dev/random and wait for it to be readable */
  422. if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {
  423. if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {
  424. FD_ZERO(&fds);
  425. FD_SET(fd, &fds);
  426. while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0
  427. && errno == EINTR);
  428. } else {
  429. while ((r = read(fd, &c, 1)) < 0 && errno == EINTR);
  430. }
  431. close(fd);
  432. if (r == 1) {
  433. seeded = 1;
  434. /* Create the shared memory indicator */
  435. shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,
  436. IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);
  437. }
  438. }
  439. }
  440. if (shm_id != -1) {
  441. seeded = 1;
  442. /*
  443. * Map the shared memory to prevent its premature destruction.
  444. * If this call fails, it isn't a big problem.
  445. */
  446. shm_addr = shmat(shm_id, NULL, SHM_RDONLY);
  447. if (shm_addr != (void *)-1)
  448. OPENSSL_atexit(&cleanup_shm);
  449. }
  450. }
  451. return seeded;
  452. }
  453. # else /* defined __linux && DEVRANDOM_WAIT && OPENSSL_RAND_SEED_GETRANDOM */
  454. static int wait_random_seeded(void)
  455. {
  456. return 1;
  457. }
  458. # endif
  459. /*
  460. * Verify that the file descriptor associated with the random source is
  461. * still valid. The rationale for doing this is the fact that it is not
  462. * uncommon for daemons to close all open file handles when daemonizing.
  463. * So the handle might have been closed or even reused for opening
  464. * another file.
  465. */
  466. static int check_random_device(struct random_device * rd)
  467. {
  468. struct stat st;
  469. return rd->fd != -1
  470. && fstat(rd->fd, &st) != -1
  471. && rd->dev == st.st_dev
  472. && rd->ino == st.st_ino
  473. && ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
  474. && rd->rdev == st.st_rdev;
  475. }
  476. /*
  477. * Open a random device if required and return its file descriptor or -1 on error
  478. */
  479. static int get_random_device(size_t n)
  480. {
  481. struct stat st;
  482. struct random_device * rd = &random_devices[n];
  483. /* reuse existing file descriptor if it is (still) valid */
  484. if (check_random_device(rd))
  485. return rd->fd;
  486. /* open the random device ... */
  487. if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
  488. return rd->fd;
  489. /* ... and cache its relevant stat(2) data */
  490. if (fstat(rd->fd, &st) != -1) {
  491. rd->dev = st.st_dev;
  492. rd->ino = st.st_ino;
  493. rd->mode = st.st_mode;
  494. rd->rdev = st.st_rdev;
  495. } else {
  496. close(rd->fd);
  497. rd->fd = -1;
  498. }
  499. return rd->fd;
  500. }
  501. /*
  502. * Close a random device making sure it is a random device
  503. */
  504. static void close_random_device(size_t n)
  505. {
  506. struct random_device * rd = &random_devices[n];
  507. if (check_random_device(rd))
  508. close(rd->fd);
  509. rd->fd = -1;
  510. }
  511. int ossl_rand_pool_init(void)
  512. {
  513. size_t i;
  514. for (i = 0; i < OSSL_NELEM(random_devices); i++)
  515. random_devices[i].fd = -1;
  516. return 1;
  517. }
  518. void ossl_rand_pool_cleanup(void)
  519. {
  520. size_t i;
  521. for (i = 0; i < OSSL_NELEM(random_devices); i++)
  522. close_random_device(i);
  523. }
  524. void ossl_rand_pool_keep_random_devices_open(int keep)
  525. {
  526. if (!keep)
  527. ossl_rand_pool_cleanup();
  528. keep_random_devices_open = keep;
  529. }
  530. # else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */
  531. int ossl_rand_pool_init(void)
  532. {
  533. return 1;
  534. }
  535. void ossl_rand_pool_cleanup(void)
  536. {
  537. }
  538. void ossl_rand_pool_keep_random_devices_open(int keep)
  539. {
  540. }
  541. # endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */
  542. /*
  543. * Try the various seeding methods in turn, exit when successful.
  544. *
  545. * If more than one entropy source is available, is it
  546. * preferable to stop as soon as enough entropy has been collected
  547. * (as favored by @rsalz) or should one rather be defensive and add
  548. * more entropy than requested and/or from different sources?
  549. *
  550. * Currently, the user can select multiple entropy sources in the
  551. * configure step, yet in practice only the first available source
  552. * will be used. A more flexible solution has been requested, but
  553. * currently it is not clear how this can be achieved without
  554. * overengineering the problem. There are many parameters which
  555. * could be taken into account when selecting the order and amount
  556. * of input from the different entropy sources (trust, quality,
  557. * possibility of blocking).
  558. */
  559. size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
  560. {
  561. # if defined(OPENSSL_RAND_SEED_NONE)
  562. return ossl_rand_pool_entropy_available(pool);
  563. # else
  564. size_t entropy_available = 0;
  565. (void)entropy_available; /* avoid compiler warning */
  566. # if defined(OPENSSL_RAND_SEED_GETRANDOM)
  567. {
  568. size_t bytes_needed;
  569. unsigned char *buffer;
  570. ssize_t bytes;
  571. /* Maximum allowed number of consecutive unsuccessful attempts */
  572. int attempts = 3;
  573. bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
  574. while (bytes_needed != 0 && attempts-- > 0) {
  575. buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
  576. bytes = syscall_random(buffer, bytes_needed);
  577. if (bytes > 0) {
  578. ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
  579. bytes_needed -= bytes;
  580. attempts = 3; /* reset counter after successful attempt */
  581. } else if (bytes < 0 && errno != EINTR) {
  582. break;
  583. }
  584. }
  585. }
  586. entropy_available = ossl_rand_pool_entropy_available(pool);
  587. if (entropy_available > 0)
  588. return entropy_available;
  589. # endif
  590. # if defined(OPENSSL_RAND_SEED_LIBRANDOM)
  591. {
  592. /* Not yet implemented. */
  593. }
  594. # endif
  595. # if defined(OPENSSL_RAND_SEED_DEVRANDOM)
  596. if (wait_random_seeded()) {
  597. size_t bytes_needed;
  598. unsigned char *buffer;
  599. size_t i;
  600. bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
  601. for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);
  602. i++) {
  603. ssize_t bytes = 0;
  604. /* Maximum number of consecutive unsuccessful attempts */
  605. int attempts = 3;
  606. const int fd = get_random_device(i);
  607. if (fd == -1)
  608. continue;
  609. while (bytes_needed != 0 && attempts-- > 0) {
  610. buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
  611. bytes = read(fd, buffer, bytes_needed);
  612. if (bytes > 0) {
  613. ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
  614. bytes_needed -= bytes;
  615. attempts = 3; /* reset counter on successful attempt */
  616. } else if (bytes < 0 && errno != EINTR) {
  617. break;
  618. }
  619. }
  620. if (bytes < 0 || !keep_random_devices_open)
  621. close_random_device(i);
  622. bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
  623. }
  624. entropy_available = ossl_rand_pool_entropy_available(pool);
  625. if (entropy_available > 0)
  626. return entropy_available;
  627. }
  628. # endif
  629. # if defined(OPENSSL_RAND_SEED_RDTSC)
  630. entropy_available = ossl_prov_acquire_entropy_from_tsc(pool);
  631. if (entropy_available > 0)
  632. return entropy_available;
  633. # endif
  634. # if defined(OPENSSL_RAND_SEED_RDCPU)
  635. entropy_available = ossl_prov_acquire_entropy_from_cpu(pool);
  636. if (entropy_available > 0)
  637. return entropy_available;
  638. # endif
  639. # if defined(OPENSSL_RAND_SEED_EGD)
  640. {
  641. static const char *paths[] = { DEVRANDOM_EGD, NULL };
  642. size_t bytes_needed;
  643. unsigned char *buffer;
  644. int i;
  645. bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
  646. for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {
  647. size_t bytes = 0;
  648. int num;
  649. buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
  650. num = RAND_query_egd_bytes(paths[i],
  651. buffer, (int)bytes_needed);
  652. if (num == (int)bytes_needed)
  653. bytes = bytes_needed;
  654. ossl_rand_pool_add_end(pool, bytes, 8 * bytes);
  655. bytes_needed = ossl_rand_pool_bytes_needed(pool, 1);
  656. }
  657. entropy_available = ossl_rand_pool_entropy_available(pool);
  658. if (entropy_available > 0)
  659. return entropy_available;
  660. }
  661. # endif
  662. return ossl_rand_pool_entropy_available(pool);
  663. # endif
  664. }
  665. # endif
  666. #endif
  667. #if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
  668. || defined(__DJGPP__)
  669. int ossl_pool_add_nonce_data(RAND_POOL *pool)
  670. {
  671. struct {
  672. pid_t pid;
  673. CRYPTO_THREAD_ID tid;
  674. uint64_t time;
  675. } data;
  676. /* Erase the entire structure including any padding */
  677. memset(&data, 0, sizeof(data));
  678. /*
  679. * Add process id, thread id, and a high resolution timestamp to
  680. * ensure that the nonce is unique with high probability for
  681. * different process instances.
  682. */
  683. data.pid = getpid();
  684. data.tid = CRYPTO_THREAD_get_current_id();
  685. data.time = get_time_stamp();
  686. return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
  687. }
  688. int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
  689. {
  690. struct {
  691. int fork_id;
  692. CRYPTO_THREAD_ID tid;
  693. uint64_t time;
  694. } data;
  695. /* Erase the entire structure including any padding */
  696. memset(&data, 0, sizeof(data));
  697. /*
  698. * Add some noise from the thread id and a high resolution timer.
  699. * The fork_id adds some extra fork-safety.
  700. * The thread id adds a little randomness if the drbg is accessed
  701. * concurrently (which is the case for the <master> drbg).
  702. */
  703. data.fork_id = openssl_get_fork_id();
  704. data.tid = CRYPTO_THREAD_get_current_id();
  705. data.time = get_timer_bits();
  706. return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
  707. }
  708. /*
  709. * Get the current time with the highest possible resolution
  710. *
  711. * The time stamp is added to the nonce, so it is optimized for not repeating.
  712. * The current time is ideal for this purpose, provided the computer's clock
  713. * is synchronized.
  714. */
  715. static uint64_t get_time_stamp(void)
  716. {
  717. # if defined(OSSL_POSIX_TIMER_OKAY)
  718. {
  719. struct timespec ts;
  720. if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
  721. return TWO32TO64(ts.tv_sec, ts.tv_nsec);
  722. }
  723. # endif
  724. # if defined(__unix__) \
  725. || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
  726. {
  727. struct timeval tv;
  728. if (gettimeofday(&tv, NULL) == 0)
  729. return TWO32TO64(tv.tv_sec, tv.tv_usec);
  730. }
  731. # endif
  732. return time(NULL);
  733. }
  734. /*
  735. * Get an arbitrary timer value of the highest possible resolution
  736. *
  737. * The timer value is added as random noise to the additional data,
  738. * which is not considered a trusted entropy sourec, so any result
  739. * is acceptable.
  740. */
  741. static uint64_t get_timer_bits(void)
  742. {
  743. uint64_t res = OPENSSL_rdtsc();
  744. if (res != 0)
  745. return res;
  746. # if defined(__sun) || defined(__hpux)
  747. return gethrtime();
  748. # elif defined(_AIX)
  749. {
  750. timebasestruct_t t;
  751. read_wall_time(&t, TIMEBASE_SZ);
  752. return TWO32TO64(t.tb_high, t.tb_low);
  753. }
  754. # elif defined(OSSL_POSIX_TIMER_OKAY)
  755. {
  756. struct timespec ts;
  757. # ifdef CLOCK_BOOTTIME
  758. # define CLOCK_TYPE CLOCK_BOOTTIME
  759. # elif defined(_POSIX_MONOTONIC_CLOCK)
  760. # define CLOCK_TYPE CLOCK_MONOTONIC
  761. # else
  762. # define CLOCK_TYPE CLOCK_REALTIME
  763. # endif
  764. if (clock_gettime(CLOCK_TYPE, &ts) == 0)
  765. return TWO32TO64(ts.tv_sec, ts.tv_nsec);
  766. }
  767. # endif
  768. # if defined(__unix__) \
  769. || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
  770. {
  771. struct timeval tv;
  772. if (gettimeofday(&tv, NULL) == 0)
  773. return TWO32TO64(tv.tv_sec, tv.tv_usec);
  774. }
  775. # endif
  776. return time(NULL);
  777. }
  778. #endif /* (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS))
  779. || defined(__DJGPP__) */