public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 3/4] Deprecate DES encryption functions.
  2018-05-06 17:52 [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Zack Weinberg
@ 2018-05-06 17:51 ` Zack Weinberg
  2018-05-08 14:33   ` Florian Weimer
  2018-05-06 17:52 ` [PATCH 2/4] Revise manual sections on cryptography and random numbers Zack Weinberg
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2018-05-06 17:51 UTC (permalink / raw)
  To: libc-alpha; +Cc: carlos, fweimer, rj

The functions encrypt, setkey, encrypt_r, setkey_r, cbc_crypt,
ecb_crypt, and des_setparity should not be used in new programs,
because they use the DES block cipher, which is unacceptably weak by
modern standards.  Mark all of them with __attribute_deprecated__.

cbc_crypt, ecb_crypt, and des_setparity are already compat symbols
when glibc is configured with --disable-obsolete-rpc.  I think it is
appropriate to keep encrypt, setkey, encrypt_r, and setkey_r as normal
symbols until they are formally deprecated in POSIX
(see http://austingroupbugs.net/view.php?id=1192 for the status of
that process).

DES-based authentication for Sun RPC is also insecure and should be
deprecated or even removed, but maybe that can be left as TI-RPC's
problem.

	* crypt/crypt.h: Update comments above encrypt and setkey.  Mark
	encrypt, setkey, encrypt_r, and setkey_r with __attribute_deprecated__.
        * posix/unistd.h: Update comments above encrypt.
        Mark encrypt with __attribute_deprecated__.
        * stdlib/stdlib.h: Update comments above setkey.
        Mark setkey with __attribute_deprecated__.
	* sunrpc/rpc/des_crypt.h: Add comment explaining why none of
	these functions should be used in new programs.  Mark cbc_crypt,
	ecb_crypt, and des_setparity with __attribute_deprecated__.

	* crypt/Makefile: Use -Wno-deprecated-declarations for the test
	program cert.c.
        * sunrpc/Makefile: Use -Wno-deprecated-declarations for
	auth_des.c, des_crypt.c, des_soft.c, svcauth_des.c, and xcrypt.c.
---
 NEWS                   |  8 ++++++++
 crypt/Makefile         |  3 +++
 crypt/crypt.h          | 17 +++++++++++------
 posix/unistd.h         |  8 +++++---
 stdlib/stdlib.h        |  9 +++++++--
 sunrpc/Makefile        |  9 +++++++++
 sunrpc/rpc/des_crypt.h | 11 ++++++++---
 7 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/NEWS b/NEWS
index 5155c86318..2fe2da8b59 100644
--- a/NEWS
+++ b/NEWS
@@ -63,6 +63,14 @@ Deprecated and removed features, and other changes affecting compatibility:
   binaries; the headers <ustat.h> and <sys/ustat.h> have been removed.  This
   function has been deprecated in favor of fstatfs and statfs.
 
+* The functions 'encrypt', 'encrypt_r', 'setkey', 'setkey_r', 'cbc_crypt',
+  'ecb_crypt', and 'des_setparity' are deprecated.  They encrypt and decrypt
+  data with the DES block cipher, which is no longer considered secure.
+  Also, encrypt, encrypt_r, setkey, and setkey_r require awkward pre- and
+  post-processing of the encryption key and data to be encrypted, and
+  encrypt and setkey are not thread-safe.  Software that still uses these
+  functions should switch to a modern cryptography library, such as GnuTLS.
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/crypt/Makefile b/crypt/Makefile
index 303800df73..e122bcebf0 100644
--- a/crypt/Makefile
+++ b/crypt/Makefile
@@ -32,6 +32,9 @@ libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
 
 tests := cert md5c-test sha256c-test sha512c-test badsalttest
 
+# cert.c tests the deprecated setkey/encrypt interface
+CFLAGS-cert.c = -Wno-deprecated-declarations
+
 ifeq ($(crypt-in-libc),yes)
 routines += $(libcrypt-routines)
 endif
diff --git a/crypt/crypt.h b/crypt/crypt.h
index 5da098b715..22cf13ff89 100644
--- a/crypt/crypt.h
+++ b/crypt/crypt.h
@@ -32,13 +32,18 @@ __BEGIN_DECLS
 extern char *crypt (const char *__key, const char *__salt)
      __THROW __nonnull ((1, 2));
 
-/* Setup DES tables according KEY.  */
-extern void setkey (const char *__key) __THROW __nonnull ((1));
+/* Set the encryption key for subsequent calls to 'encrypt'.
+   This function should not be used in new programs, because the cipher
+   it uses is DES, which is unacceptably weak by modern standards.  */
+extern void setkey (const char *__key)
+     __THROW __nonnull ((1)) __attribute_deprecated__;
 
 /* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
-   block in place.  */
+   block in place.  The key is controlled by 'setkey'.
+   This function should not be used in new programs, because the cipher
+   it uses is DES, which is unacceptably weak by modern standards.  */
 extern void encrypt (char *__glibc_block, int __edflag)
-     __THROW __nonnull ((1));
+     __THROW __nonnull ((1)) __attribute_deprecated__;
 
 #ifdef __USE_GNU
 /* Reentrant versions of the functions above.  The additional argument
@@ -63,11 +68,11 @@ extern char *crypt_r (const char *__key, const char *__salt,
 
 extern void setkey_r (const char *__key,
 		      struct crypt_data * __restrict __data)
-     __THROW __nonnull ((1, 2));
+     __THROW __nonnull ((1, 2)) __attribute_deprecated__;
 
 extern void encrypt_r (char *__glibc_block, int __edflag,
 		       struct crypt_data * __restrict __data)
-     __THROW __nonnull ((1, 3));
+     __THROW __nonnull ((1, 3)) __attribute_deprecated__;
 #endif
 
 __END_DECLS
diff --git a/posix/unistd.h b/posix/unistd.h
index 4d149f9945..5d4e07f6c8 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -1127,10 +1127,12 @@ extern char *crypt (const char *__key, const char *__salt)
      __THROW __nonnull ((1, 2));
 
 /* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
-   block in place.  */
-extern void encrypt (char *__glibc_block, int __edflag)
-     __THROW __nonnull ((1));
+   block in place.  The key is controlled by 'setkey', in stdlib.h.
 
+   This function should not be used in new programs, because the cipher
+   it uses is DES, which is unacceptably weak by modern standards.  */
+extern void encrypt (char *__glibc_block, int __edflag)
+     __THROW __nonnull ((1)) __attribute_deprecated__;
 
 /* Swab pairs bytes in the first N bytes of the area pointed to by
    FROM and copy the result to TO.  The value of TO must not be in the
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 6b1ead31e0..5b104bcc51 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -959,8 +959,13 @@ extern int getsubopt (char **__restrict __optionp,
 
 
 #ifdef __USE_XOPEN
-/* Setup DES tables according KEY.  */
-extern void setkey (const char *__key) __THROW __nonnull ((1));
+/* Set the encryption key for subsequent calls to 'encrypt', which is
+   declared in unistd.h.
+
+   This function should not be used in new programs, because the cipher
+   it uses is DES, which is unacceptably weak by modern standards.  */
+extern void setkey (const char *__key)
+     __THROW __nonnull ((1)) __attribute_deprecated__;
 #endif
 
 
diff --git a/sunrpc/Makefile b/sunrpc/Makefile
index 8f2a3c8213..07fb90de6b 100644
--- a/sunrpc/Makefile
+++ b/sunrpc/Makefile
@@ -156,6 +156,15 @@ CFLAGS-pmap_rmt.c += -fexceptions
 CFLAGS-clnt_perr.c += -fexceptions
 CFLAGS-openchild.c += -fexceptions
 
+# These files implement Secure RPC authentication using DES, which is
+# no longer secure and has had some of the associated functions tagged
+# __attribute_deprecated__.
+CFLAGS-auth_des.c += -Wno-deprecated-declarations
+CFLAGS-des_crypt.c += -Wno-deprecated-declarations
+CFLAGS-des_soft.c += -Wno-deprecated-declarations
+CFLAGS-svcauth_des.c += -Wno-deprecated-declarations
+CFLAGS-xcrypt.c += -Wno-deprecated-declarations
+
 sunrpc-CPPFLAGS = -D_RPC_THREAD_SAFE_
 CPPFLAGS += $(sunrpc-CPPFLAGS)
 BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS)
diff --git a/sunrpc/rpc/des_crypt.h b/sunrpc/rpc/des_crypt.h
index 77cca3cbed..85875afa11 100644
--- a/sunrpc/rpc/des_crypt.h
+++ b/sunrpc/rpc/des_crypt.h
@@ -70,6 +70,10 @@ __BEGIN_DECLS
  * DESERR_NOHWDEVICE is returned if DES_HW was specified but
  * there was no hardware to do it on (the data will still be
  * encrypted though, in software).
+ *
+ * None of the functions in this header should be used in new programs,
+ * because the cipher they use is DES, which is unacceptably weak by
+ * modern standards.
  */
 
 
@@ -77,19 +81,20 @@ __BEGIN_DECLS
  * Cipher Block Chaining mode
  */
 extern int cbc_crypt (char *__key, char *__buf, unsigned __len,
-		      unsigned __mode, char *__ivec) __THROW;
+		      unsigned __mode, char *__ivec)
+  __THROW __attribute_deprecated__;
 
 /*
  * Electronic Code Book mode
  */
 extern int ecb_crypt (char *__key, char *__buf, unsigned __len,
-		      unsigned __mode) __THROW;
+		      unsigned __mode) __THROW __attribute_deprecated__;
 
 /*
  * Set des parity for a key.
  * DES parity is odd and in the low bit of each byte
  */
-extern void des_setparity (char *__key) __THROW;
+extern void des_setparity (char *__key) __THROW __attribute_deprecated__;
 
 __END_DECLS
 
-- 
2.17.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt
@ 2018-05-06 17:52 Zack Weinberg
  2018-05-06 17:51 ` [PATCH 3/4] Deprecate DES encryption functions Zack Weinberg
                   ` (4 more replies)
  0 siblings, 5 replies; 19+ messages in thread
From: Zack Weinberg @ 2018-05-06 17:52 UTC (permalink / raw)
  To: libc-alpha; +Cc: carlos, fweimer, rj

As requested by Rical Jasan, this revision of the patchset
<https://sourceware.org/ml/libc-alpha/2018-04/msg00628.html> carefully
splits the documentation changes into one patch that just moves text
around, and another patch that changes text but doesn't move it.  I
have also made some more improvements to the documentation.  There are
no new changes to code.

Rical said:

> I have some concern over the creation of a whole chapter for "Obsolete
> Encryption".  I don't think that sets a desirable precedent for chapter
> topics.  I think combining the disparate sections on randomness is a
> good call, though.
>
> What do you think about continuing to use crypt.texi for crytographic
> topics and creating sections for "Obsolete Encryption" and "Random
> Number Generation" there (while otherwise keeping the rest of the
> changes, such as dropping "Legal Problems" and FIPS compliance, updating
> the description of crypt, etc.)?  "Password Handling" could likewise be
> made its own section.

I agree that "Obsolete Encryption" does not need to be its own
chapter; in this revision it goes back to being a subsection of
crypt.texi.  "Random Number Generation" is still a new independent
chapter.  This is because I want to put "Unpredictable Bytes" right
after "Pseudo-Random Number Generation", and it doesn't seem to make
sense to have that consolidated subtree be either with math.texi or
crypt.texi.

I am not sure whether I remembered to address all of your other
comments on the documentation changes, but I got the impression you
wanted to re-review it from scratch anyway after the split-up?

Zack Weinberg (4):
  Reorganize manual sections on cryptography and random numbers.
  Revise manual sections on cryptography and random numbers.
  Deprecate DES encryption functions.
  New configure option --disable-crypt.

 INSTALL                    |  11 +
 Makeconfig                 |   9 +-
 NEWS                       |  20 +
 config.make.in             |   1 +
 configure                  |  18 +
 configure.ac               |  11 +
 conform/Makefile           |  11 +-
 crypt/Makefile             |   5 +-
 crypt/crypt.h              |  22 +-
 elf/Makefile               |  27 +-
 elf/tst-linkall-static.c   |   4 +-
 manual/Makefile            |   2 +-
 manual/arith.texi          |   2 +-
 manual/crypt.texi          | 662 +++++++++++++-------------------
 manual/examples/genpass.c  |  38 +-
 manual/examples/testpass.c |  34 +-
 manual/install.texi        |  12 +
 manual/math.texi           | 586 +---------------------------
 manual/random.texi         | 754 +++++++++++++++++++++++++++++++++++++
 manual/string.texi         |   6 +-
 manual/terminal.texi       |  45 +++
 manual/time.texi           |   2 +-
 posix/unistd.h             |  15 +-
 stdlib/stdlib.h            |   9 +-
 sunrpc/Makefile            |   9 +
 sunrpc/rpc/des_crypt.h     |  11 +-
 26 files changed, 1282 insertions(+), 1044 deletions(-)
 create mode 100644 manual/random.texi

-- 
2.17.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 2/4] Revise manual sections on cryptography and random numbers.
  2018-05-06 17:52 [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Zack Weinberg
  2018-05-06 17:51 ` [PATCH 3/4] Deprecate DES encryption functions Zack Weinberg
@ 2018-05-06 17:52 ` Zack Weinberg
  2018-05-08 14:23   ` Florian Weimer
  2018-05-09 11:36   ` Rical Jasan
  2018-05-06 17:52 ` [PATCH 4/4] New configure option --disable-crypt Zack Weinberg
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 19+ messages in thread
From: Zack Weinberg @ 2018-05-06 17:52 UTC (permalink / raw)
  To: libc-alpha; +Cc: carlos, fweimer, rj

This is a major rewrite of the description of 'crypt'.  It also makes
minor improvements to the description of the obsolete DES functions,
and introduces some new introductory exposition to the "random number
generation" chapter.

A few highlights of the content changes:

 - All references to FIPS have been removed.  The "Legal Problems"
   section has also been removed, but I left a one-paragraph
   cautionary note that there _are_, or have been, legal problems at
   the top of the chapter.  I also removed the paragraph saying that
   systems not connected to a network need no user authentication,
   because that's a pretty rare situation nowadays.  (It still says
   "sometimes it is necessary" to authenticate the user, though.)

 - I added documentation for all of the hash functions that glibc
   actually supports, but not for the additional hash functions
   supported by libxcrypt.  If we're going to keep this manual section
   around after the transition is more advanced, it would probably
   make sense to add them then.

 - There is much more detailed discussion of how to generate a salt,
   and the failure behavior for crypt is documented.  (Returning an
   invalid hash on failure is what libxcrypt does; Solar Designer's
   notes say that this was done "for compatibility with old programs
   that assume crypt can never fail".)

 - As far as I can tell, the header 'crypt.h' is entirely a GNU
   invention, and never existed on any other Unix lineage.  The
   functions 'crypt', 'encrypt', and 'setkey', however, were in Issue
   1 of the SVID and are now in the XSI component of POSIX.  I tried
   to make all of the @standards annotations consistent with this, but
   I'm not sure I got them perfectly right.

 - The genpass.c example has been improved to use getentropy instead
   of the current time to generate the salt.  It uses more random
   bytes than is strictly necessary because I didn't want to
   complicate the code with proper base64 encoding.

 - The testpass.c example has been improved to take a username as a
   command-line argument and validate that user's password, instead of
   hardwiring a hash.  It really ought to read passwords out of the
   shadow file (getspnam() instead of getpwnam()), but we don't have
   any documentation for the shadow file functions, and I don't want
   to delay this work even more by writing some.

 - I tried to make the explanation of the encoding of the arguments to
   'encrypt' and 'setkey' better.  It's still a bit confusing but I
   don't think it's worth spending any more effort on.

 - I changed "hardware device" to "hardware DES accelerator" because a
   hardware device could be anything.

 - DES_FAILED is a macro, not a function, and the description of the
   value it returns was backwards.

	* manual/crypt.texi (Cryptographic Functions): New initial
	exposition.
	(Legal Problems): Section removed, replaced by a short caution in
	the initial exposition for 'Cryptographic Functions'.
	(crypt): Section renamed to 'Password Storage'.  Full rewrite.
	(DES Encryption): Section renamed to 'Obsolete Encryption'.
	Remove all mention of FIPS.  State clearly that none of these
	functions should be used anymore.  Various other improvements to
	the text.
	* manual/examples/genpass.c: Generate a salt using getentropy
	instead of the current time.
	* manual/examples/testpass.c: Instead of a hard-coded password
	hash, demonstrate reading passwords from the user database.
	* manual/string.texi (strfry, memfrob): Remove cross-references to
	the obsolete DES encryption functions.

	* manual/random.texi (Random Number Generation): New initial
	exposition.
	(Pseudo-Random Numbers): No need to xref the very next section.
	(Unpredictable Bytes): Improve initial exposition.  Clarify error
	behavior of getentropy and getrandom.
---
 manual/crypt.texi          | 445 ++++++++++++++++++++-----------------
 manual/examples/genpass.c  |  38 ++--
 manual/examples/testpass.c |  34 ++-
 manual/random.texi         |  84 +++++--
 manual/string.texi         |   6 +-
 5 files changed, 358 insertions(+), 249 deletions(-)

diff --git a/manual/crypt.texi b/manual/crypt.texi
index c24306c07c..a3c02be055 100644
--- a/manual/crypt.texi
+++ b/manual/crypt.texi
@@ -2,73 +2,35 @@
 @chapter Cryptographic Functions
 @c %MENU% Password storage and obsolete encryption functions
 
-@vindex AUTH_DES
-@cindex FIPS 140-2
-It also provides support for Secure RPC, and some library functions that
-can be used to perform normal DES encryption.  The @code{AUTH_DES}
-authentication flavor in Secure RPC, as provided by @theglibc{},
-uses DES and does not comply with FIPS 140-2 nor does any other use of DES
-within @theglibc{}.  It is recommended that Secure RPC should not be used
-for systems that need to comply with FIPS 140-2 since all flavors of
-encrypted authentication use normal DES.
+@Theglibc{} is not a general-purpose cryptography library, but it does
+include one-way hash functions for password storage, and a set of
+encryption functions based on the obsolete DES block cipher.  The
+latter are present for historical reasons only, and should not be used
+at all anymore; any existing programs that still use them need to be
+updated to use ciphers that are still secure.
+
+Many countries have historically placed legal restrictions on the
+import, export, possession, or use of cryptographic tools.  These
+restrictions change frequently, so we cannot give you specific advice
+about what the situation might be in your country.  To the best of our
+knowledge, no one has objected to the export or import of @theglibc{}
+in many years, but if you are writing a program that performs
+cryptographic operations, we advise you to find out what your
+country's laws might be, first.  The one-way hash functions for
+password storage are less likely to be restricted than the DES-based
+encryption functions, because they cannot be used to send secret
+messages---the recipient would not be able to decrypt them.
 
 @menu
-* Legal Problems::              This software can get you locked up, or worse.
-* crypt::                       A one-way function for passwords.
-* DES Encryption::              Routines for DES encryption.
+* Password Storage::		A one-way function for passwords.
+* Obsolete Encryption::		Routines for encrypting and decrypting
+				  data using the obsolete DES block cipher.
 @end menu
 
-@node Legal Problems
-@section Legal Problems
-
-Because of the continuously changing state of the law, it's not possible
-to provide a definitive survey of the laws affecting cryptography.
-Instead, this section warns you of some of the known trouble spots; this
-may help you when you try to find out what the laws of your country are.
-
-Some countries require that you have a license to use, possess, or import
-cryptography.  These countries are believed to include Byelorussia,
-Burma, India, Indonesia, Israel, Kazakhstan, Pakistan, Russia, and Saudi
-Arabia.
-
-Some countries restrict the transmission of encrypted messages by radio;
-some telecommunications carriers restrict the transmission of encrypted
-messages over their network.
-
-Many countries have some form of export control for encryption software.
-The Wassenaar Arrangement is a multilateral agreement between 33
-countries (Argentina, Australia, Austria, Belgium, Bulgaria, Canada, the
-Czech Republic, Denmark, Finland, France, Germany, Greece, Hungary,
-Ireland, Italy, Japan, Luxembourg, the Netherlands, New Zealand, Norway,
-Poland, Portugal, the Republic of Korea, Romania, the Russian
-Federation, the Slovak Republic, Spain, Sweden, Switzerland, Turkey,
-Ukraine, the United Kingdom and the United States) which restricts some
-kinds of encryption exports.  Different countries apply the arrangement
-in different ways; some do not allow the exception for certain kinds of
-``public domain'' software (which would include this library), some
-only restrict the export of software in tangible form, and others impose
-significant additional restrictions.
-
-The United States has additional rules.  This software would generally
-be exportable under 15 CFR 740.13(e), which permits exports of
-``encryption source code'' which is ``publicly available'' and which is
-``not subject to an express agreement for the payment of a licensing fee or
-royalty for commercial production or sale of any product developed with
-the source code'' to most countries.
-
-The rules in this area are continuously changing.  If you know of any
-information in this manual that is out-of-date, please report it to
-the bug database.  @xref{Reporting Bugs}.
-
-@node crypt
-@section Encrypting Passwords
-
-On many systems, it is unnecessary to have any kind of user
-authentication; for instance, a workstation which is not connected to a
-network probably does not need any user authentication, because to use
-the machine an intruder must have physical access.
-
-Sometimes, however, it is necessary to be sure that a user is authorized
+@node Password Storage
+@section Password Storage
+
+Sometimes it is necessary to be sure that a user is authorized
 to use some service a machine provides---for instance, to log in as a
 particular user id (@pxref{Users and Groups}).  One traditional way of
 doing this is for each user to choose a secret @dfn{password}; then, the
@@ -76,164 +38,224 @@ system can ask someone claiming to be a user what the user's password
 is, and if the person gives the correct password then the system can
 grant the appropriate privileges.
 
-If all the passwords are just stored in a file somewhere, then this file
-has to be very carefully protected.  To avoid this, passwords are run
-through a @dfn{one-way function}, a function which makes it difficult to
-work out what its input was by looking at its output, before storing in
-the file.
-
-@Theglibc{} provides a one-way function that is compatible with
-the behavior of the @code{crypt} function introduced in FreeBSD 2.0.
-It supports two one-way algorithms: one based on the MD5
-message-digest algorithm that is compatible with modern BSD systems,
-and the other based on the Data Encryption Standard (DES) that is
-compatible with Unix systems.
-
-@deftypefun {char *} crypt (const char *@var{key}, const char *@var{salt})
-@standards{BSD, crypt.h}
-@standards{SVID, crypt.h}
+Programs that handle passwords must take special care not to reveal
+them to anyone, no matter what.  It is not enough to keep them in a
+file that is only accessible with special privileges.  The file might
+be ``leaked'' via a bug or misconfiguration, and system administrators
+shouldn't learn everyone's password even if they have to edit that
+file for some reason.  To avoid this, passwords should also be
+converted into @dfn{one-way hashes}, using a @dfn{one-way function},
+before they are stored.  It is believed that the only way to recover a
+password from its one-way hash is to guess possible passwords, hash
+them, and compare the output with the hashes stored in the password
+file.  The one-way functions are designed to make this process
+impractically slow, for all but the most obvious guesses.  (Do not use
+a word from the dictionary as your password.)
+
+@Theglibc{} provides an interface to four different one-way functions,
+based on the SHA-2-512, SHA-2-256, MD5, and DES cryptographic
+primitives.  New passwords should be hashed with either of the
+SHA-based functions.  The others are too weak for newly set passwords,
+but we continue to support them for verifying old passwords.  The
+DES-based hash is especially weak, because it ignores all but the
+first eight characters of its input.
+
+@deftypefun {char *} crypt (const char *@var{phrase}, const char *@var{salt})
+@standards{X/Open, unistd.h}
+@standards{GNU, crypt.h}
 @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
 @c Besides the obvious problem of returning a pointer into static
 @c storage, the DES initializer takes an internal lock with the usual
-@c set of problems for AS- and AC-Safety.  The FIPS mode checker and the
-@c NSS implementations of may leak file descriptors if canceled.  The
+@c set of problems for AS- and AC-Safety.
+@c The NSS implementations may leak file descriptors if cancelled.
 @c The MD5, SHA256 and SHA512 implementations will malloc on long keys,
 @c and NSS relies on dlopening, which brings about another can of worms.
 
-The @code{crypt} function takes a password, @var{key}, as a string, and
-a @var{salt} character array which is described below, and returns a
-printable ASCII string which starts with another salt.  It is believed
-that, given the output of the function, the best way to find a @var{key}
-that will produce that output is to guess values of @var{key} until the
-original value of @var{key} is found.
-
-The @var{salt} parameter does two things.  Firstly, it selects which
-algorithm is used, the MD5-based one or the DES-based one.  Secondly, it
-makes life harder for someone trying to guess passwords against a file
-containing many passwords; without a @var{salt}, an intruder can make a
-guess, run @code{crypt} on it once, and compare the result with all the
-passwords.  With a @var{salt}, the intruder must run @code{crypt} once
-for each different salt.
-
-For the MD5-based algorithm, the @var{salt} should consist of the string
-@code{$1$}, followed by up to 8 characters, terminated by either
-another @code{$} or the end of the string.  The result of @code{crypt}
-will be the @var{salt}, followed by a @code{$} if the salt didn't end
-with one, followed by 22 characters from the alphabet
-@code{./0-9A-Za-z}, up to 34 characters total.  Every character in the
-@var{key} is significant.
-
-For the DES-based algorithm, the @var{salt} should consist of two
-characters from the alphabet @code{./0-9A-Za-z}, and the result of
-@code{crypt} will be those two characters followed by 11 more from the
-same alphabet, 13 in total.  Only the first 8 characters in the
-@var{key} are significant.
-
-The MD5-based algorithm has no limit on the useful length of the
-password used, and is slightly more secure.  It is therefore preferred
-over the DES-based algorithm.
-
-When the user enters their password for the first time, the @var{salt}
-should be set to a new string which is reasonably random.  To verify a
-password against the result of a previous call to @code{crypt}, pass
-the result of the previous call as the @var{salt}.
+The function @code{crypt} converts a password string, @var{phrase},
+into a one-way hash suitable for storage in the user database.  The
+hash will consist entirely of printable ASCII characters.  It will not
+contain whitespace, nor any of the characters @kbd{:}, @kbd{;},
+@kbd{*}, @kbd{!}, or @kbd{\}.
+
+The @var{salt} parameter controls which one-way function is used, and
+it also ensures that the output of the one-way function is different
+for every user, even if they have the same password.  This makes it
+harder to guess passwords from a large user database.  Without salt,
+the intruder could make a guess, run @code{crypt} on it once, and
+compare the result with all the hashed passwords.  Salt forces the
+intruder to make many calls to @code{crypt} for each guess.
+
+To verify a password, pass the previously hashed password as the
+@var{salt}.  To hash a new password for storage, set @var{salt} to a
+string consisting of a prefix plus a sequence of randomly chosen
+characters, according to this table:
+
+@multitable @columnfractions .15 .1 .3
+@headitem Algorithm @tab Prefix @tab Random sequence
+@item SHA-2-512
+@tab @samp{$6$}
+@tab 16 characters
+@item SHA-2-256
+@tab @samp{$5$}
+@tab 16 characters
+@item MD5
+@tab @samp{$1$}
+@tab 8 characters
+@item DES
+@tab @samp{}
+@tab 2 characters
+@end multitable
+
+In all cases, the random characters should be chosen from the alphabet
+@code{./0-9A-Za-z}.
+
+With all of the hash functions @emph{except} DES, @var{phrase} can be
+arbitrarily long, and all eight bits of each byte are significant.
+With DES, all but the first eight characters of @var{phrase} are ignored,
+and the eighth bit of each byte is also ignored.
+
+@code{crypt} can fail.  Some implementations return @code{NULL} on
+failure, and others return an @emph{invalid} hashed passphrase, which
+will begin with a @kbd{*} and will not be the same as @var{salt}.  In
+either case, @code{errno} will be set to indicate the problem.  Some
+of the possible error codes are:
+
+@table @code
+@item EINVAL
+@var{salt} is invalid; neither a previously hashed password, nor a
+well-formed new salt for any of the supported hash functions.
+
+@item EPERM
+The hash function selected by @var{salt} has been disabled by local
+policy.
+
+@item ENOMEM
+Failed to allocate internal scratch storage.
+
+@item ENOSYS
+@itemx EOPNOTSUPP
+Hashing passphrases is not supported at all, or the hash function
+selected by @var{salt} is not supported.  @Theglibc{} does not use
+these error codes, but they may be encountered on other operating
+systems.
+@end table
+
+@code{crypt} uses static storage for both internal scratchwork and the
+string it returns.  It is not safe to call @code{crypt} from multiple
+threads simultaneously, and the string it returns will be overwritten
+by any subsequent call to @code{crypt}.
+
+@code{crypt} is specified in the X/Open Portability Guide and is
+present on nearly all historical Unix systems.  However, XPG does not
+specify any one-way functions.
+
+@code{crypt} is declared in @file{unistd.h}.  @Theglibc{} also
+declares this function in @file{crypt.h}.
 @end deftypefun
 
-@deftypefun {char *} crypt_r (const char *@var{key}, const char *@var{salt}, {struct crypt_data *} @var{data})
+@deftypefun {char *} crypt_r (const char *@var{phrase}, const char *@var{salt}, {struct crypt_data *} @var{data})
 @standards{GNU, crypt.h}
 @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
 @c Compared with crypt, this function fixes the @mtasurace:crypt
 @c problem, but nothing else.
 
-The @code{crypt_r} function does the same thing as @code{crypt}, but
-takes an extra parameter which includes space for its result (among
-other things), so it can be reentrant.  @code{data@w{->}initialized} must be
-cleared to zero before the first time @code{crypt_r} is called.
-
-The @code{crypt_r} function is a GNU extension.
+The function @code{crypt_r} is a reentrant version of @code{crypt}.
+Instead of static storage, it uses the memory pointed to by its
+@var{data} argument for both scratchwork and the string it returns.
+It can safely be used from multiple threads, as long as different
+@var{data} objects are used in each thread.  The string it returns
+will still be overwritten by another call with the same @var{data}.
+@var{data} must be a pointer to a @samp{struct crypt_data} object
+allocated by the caller, and before one of these objects is used for
+the first time, it must be erased using
+@samp{@w{memset(data, 0, sizeof data)}}
+or similar.
+
+@code{crypt_r} is a GNU extension.  It is declared in @file{crypt.h},
+as is @samp{struct crypt_data}.
 @end deftypefun
 
-The @code{crypt} and @code{crypt_r} functions are prototyped in the
-header @file{crypt.h}.
-
-The following short program is an example of how to use @code{crypt} the
-first time a password is entered.  Note that the @var{salt} generation
-is just barely acceptable; in particular, it is not unique between
-machines, and in many applications it would not be acceptable to let an
-attacker know what time the user's password was last set.
+The following program shows how to use @code{crypt} the first time a
+password is entered.  It uses @code{getentropy} to make the salt as
+unpredictable as possible; @pxref{Unpredictable Bytes}.
 
 @smallexample
 @include genpass.c.texi
 @end smallexample
 
-The next program shows how to verify a password.  It prompts the user
-for a password and prints ``Access granted.'' if the user types
-@code{GNU libc manual}.
+@c When we have documentation for getspnam, change the demo to use it.
+The next program shows how to verify a password stored in the system
+user database in the traditional manner; @pxref{User Database}.  (On
+newer installations, the passwords are instead stored in a ``shadow''
+database that requires special privileges to access, and this program
+will not work.)
 
 @smallexample
 @include testpass.c.texi
 @end smallexample
 
-@node DES Encryption
-@section DES Encryption
-
-@cindex FIPS 46-3
-The Data Encryption Standard is described in the US Government Federal
-Information Processing Standards (FIPS) 46-3 published by the National
-Institute of Standards and Technology.  The DES has been very thoroughly
-analyzed since it was developed in the late 1970s, and no new
-significant flaws have been found.
-
-However, the DES uses only a 56-bit key (plus 8 parity bits), and a
-machine has been built in 1998 which can search through all possible
-keys in about 6 days, which cost about US$200000; faster searches would
-be possible with more money.  This makes simple DES insecure for most
-purposes, and NIST no longer permits new US government systems
-to use simple DES.
-
-For serious encryption functionality, it is recommended that one of the
-many free encryption libraries be used instead of these routines.
-
-The DES is a reversible operation which takes a 64-bit block and a
-64-bit key, and produces another 64-bit block.  Usually the bits are
-numbered so that the most-significant bit, the first bit, of each block
-is numbered 1.
-
-Under that numbering, every 8th bit of the key (the 8th, 16th, and so
-on) is not used by the encryption algorithm itself.  But the key must
-have odd parity; that is, out of bits 1 through 8, and 9 through 16, and
-so on, there must be an odd number of `1' bits, and this completely
-specifies the unused bits.
+@node Obsolete Encryption
+@section Obsolete Encryption
+
+For historical reasons, @theglibc{} includes several functions which
+perform encryption using the obsolete Data Encryption Standard (DES).
+None of these functions should be used anymore.  Instead, use one of
+the many free encryption libraries that use modern ciphers.
+
+DES is a block cipher standardized by the US government in 1977.  It
+is no longer considered to be secure, and has been withdrawn as a
+standard, because it only has @math{2@sup{56}} possible keys, so
+testing all of them is practical.  In 1998, it cost US$250,000 to
+build a massively parallel computer that could find the DES key that
+encrypted a known message in three days.  In 2018, the same process
+takes only one day, and there are online services that will do it for
+less than US$100 per message.
 
 @deftypefun void setkey (const char *@var{key})
-@standards{BSD, crypt.h}
-@standards{SVID, crypt.h}
+@standards{X/Open, stdlib.h}
+@standards{GNU, crypt.h}
 @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
 @c The static buffer stores the key, making it fundamentally
 @c thread-unsafe.  The locking issues are only in the initialization
 @c path; cancelling the initialization will leave the lock held, it
 @c would otherwise repeat the initialization on the next call.
 
-The @code{setkey} function sets an internal data structure to be an
-expanded form of @var{key}.  @var{key} is specified as an array of 64
-bits each stored in a @code{char}, the first bit is @code{key[0]} and
-the 64th bit is @code{key[63]}.  The @var{key} should have the correct
-parity.
+The @code{setkey} function prepares to perform DES encryption or
+decryption using the key @var{key}.  @var{key} should point to an
+array of 64 @code{char}s, each of which must be set to either @samp{0}
+or @samp{1}; that is, each byte stores one bit of the key.  Every
+eighth byte (array indices 7, 15, 23, @dots{}) must be set to give it
+plus the preceding group of seven bytes odd parity.  For instance, if
+there are three bytes set to @samp{1} among bytes 0 through 6, then
+byte 7 must be set to @samp{0}, and similarly if there are four bytes
+set to @samp{1} among bytes 8 through 14, then byte 15 must be set to
+@samp{0}, and so on.  Thus, of the 64 bytes, only 56 can be used to
+supply key data.
+
+The @code{setkey} function is specified in the X/Open Portability
+Guide and is declared in @file{stdlib.h}.  @Theglibc{} also declares
+this function in @file{crypt.h}.
 @end deftypefun
 
 @deftypefun void encrypt (char *@var{block}, int @var{edflag})
-@standards{BSD, crypt.h}
-@standards{SVID, crypt.h}
+@standards{X/Open, unistd.h}
+@standards{GNU, crypt.h}
 @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
 @c Same issues as setkey.
 
-The @code{encrypt} function encrypts @var{block} if
-@var{edflag} is 0, otherwise it decrypts @var{block}, using a key
-previously set by @code{setkey}.  The result is
-placed in @var{block}.
+The @code{encrypt} function encrypts @var{block} if @var{edflag} is 0,
+otherwise it decrypts @var{block}, using a key previously set by
+@code{setkey}.  The result overwrites the previous value of
+@var{block}.
 
-Like @code{setkey}, @var{block} is specified as an array of 64 bits each
-stored in a @code{char}, but there are no parity bits in @var{block}.
+Like @code{setkey}, @var{block} is as an array of 64 @code{char}s,
+each of which stores one bit of the block to be encrypted.  Unlike
+@code{setkey}, there are no parity bits.  All 64 of the bits are
+treated as data.
+
+The @code{encrypt} function is specified in the X/Open Portability
+Guide and is declared in @file{unistd.h}.  @Theglibc{} also declares
+this function in @file{crypt.h}.
 @end deftypefun
 
 @deftypefun void setkey_r (const char *@var{key}, {struct crypt_data *} @var{data})
@@ -245,25 +267,30 @@ stored in a @code{char}, but there are no parity bits in @var{block}.
 These are reentrant versions of @code{setkey} and @code{encrypt}.  The
 only difference is the extra parameter, which stores the expanded
 version of @var{key}.  Before calling @code{setkey_r} the first time,
-@code{data->initialized} must be cleared to zero.
-@end deftypefun
+@code{data} must be erased using
+@samp{@w{memset(data, 0, sizeof data)}}
+or similar.
 
-The @code{setkey_r} and @code{encrypt_r} functions are GNU extensions.
-@code{setkey}, @code{encrypt}, @code{setkey_r}, and @code{encrypt_r} are
-defined in @file{crypt.h}.
+@code{setkey_r} and @code{encrypt_r} are GNU extensions.  They are
+declared in @file{crypt.h}.
+@end deftypefun
 
 @deftypefun int ecb_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode})
 @standards{SUNRPC, rpc/des_crypt.h}
 @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 
 The function @code{ecb_crypt} encrypts or decrypts one or more blocks
-using DES.  Each block is encrypted independently.
+using DES.  Each block is encrypted independently, which means that if
+any two input blocks are the same, then their encryptions will also be
+the same.  This is an additional weakness in the encryption, on top of
+the weakness of DES itself.
 
 The @var{blocks} and the @var{key} are stored packed in 8-bit bytes, so
 that the first bit of the key is the most-significant bit of
 @code{key[0]} and the 63rd bit of the key is stored as the
-least-significant bit of @code{key[7]}.  The @var{key} should have the
-correct parity.
+least-significant bit of @code{key[7]}.  The least-significant bit of
+each byte must be chosen to give each byte odd parity, as with
+@code{setkey}.
 
 @var{len} is the number of bytes in @var{blocks}.  It should be a
 multiple of 8 (so that there are a whole number of blocks to encrypt).
@@ -271,33 +298,33 @@ multiple of 8 (so that there are a whole number of blocks to encrypt).
 
 The result of the encryption replaces the input in @var{blocks}.
 
-The @var{mode} parameter is the bitwise OR of two of the following:
+The @var{mode} parameter should be the bitwise OR of one of these two
+constants:
 
 @vtable @code
 @item DES_ENCRYPT
 @standards{SUNRPC, rpc/des_crypt.h}
-This constant, used in the @var{mode} parameter, specifies that
 @var{blocks} is to be encrypted.
 
 @item DES_DECRYPT
 @standards{SUNRPC, rpc/des_crypt.h}
-This constant, used in the @var{mode} parameter, specifies that
 @var{blocks} is to be decrypted.
+@end vtable
+
+@noindent
+with one of these two constants:
 
+@vtable @code
 @item DES_HW
 @standards{SUNRPC, rpc/des_crypt.h}
-This constant, used in the @var{mode} parameter, asks to use a hardware
-device.  If no hardware device is available, encryption happens anyway,
-but in software.
+Use a hardware DES accelerator, if available.  If no accelerator is
+available, encryption or decryption will still occur, but in software.
 
 @item DES_SW
 @standards{SUNRPC, rpc/des_crypt.h}
-This constant, used in the @var{mode} parameter, specifies that no
-hardware device is to be used.
+Do not use a hardware DES accelerator.
 @end vtable
 
-@end deftypefun
-
 @deftypefun int cbc_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode}, char *@var{ivec})
 @standards{SUNRPC, rpc/des_crypt.h}
 @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@@ -324,7 +351,8 @@ bytes.
 Otherwise, all the parameters are similar to those for @code{ecb_crypt}.
 @end deftypefun
 
-The result of the function will be one of these values:
+@code{ecb_crypt} and @code{cbc_crypt} both return one of the following
+values:
 
 @vtable @code
 @item DESERR_NONE
@@ -333,7 +361,7 @@ The encryption succeeded.
 
 @item DESERR_NOHWDEVICE
 @standards{SUNRPC, rpc/des_crypt.h}
-The encryption succeeded, but there was no hardware device available.
+The encryption succeeded, but there was no hardware accelerator available.
 
 @item DESERR_HWERROR
 @standards{SUNRPC, rpc/des_crypt.h}
@@ -344,13 +372,20 @@ The encryption failed because of a hardware problem.
 The encryption failed because of a bad parameter, for instance @var{len}
 is not a multiple of 8 or @var{len} is larger than @code{DES_MAXDATA}.
 @end vtable
+@end deftypefun
+
+For convenience, there is a macro which distinguishes successful from
+failure result codes:
 
-@deftypefun int DES_FAILED (int @var{err})
+@deftypefn Macro int DES_FAILED (int @var{err})
 @standards{SUNRPC, rpc/des_crypt.h}
 @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-This macro returns 1 if @var{err} is a `success' result code from
-@code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
-@end deftypefun
+This macro returns a nonzero value if @var{err} is a failure result
+code from @code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
+@end deftypefn
+
+There is also a helper function which assists in producing well-formed
+DES keys:
 
 @deftypefun void des_setparity (char *@var{key})
 @standards{SUNRPC, rpc/des_crypt.h}
diff --git a/manual/examples/genpass.c b/manual/examples/genpass.c
index 5edb2e9b8a..fe10a847cf 100644
--- a/manual/examples/genpass.c
+++ b/manual/examples/genpass.c
@@ -16,34 +16,44 @@
 */
 
 #include <stdio.h>
-#include <time.h>
 #include <unistd.h>
 #include <crypt.h>
 
 int
 main(void)
 {
-  unsigned long seed[2];
-  char salt[] = "$1$........";
-  const char *const seedchars =
+  unsigned char ubytes[16];
+  char salt[20];
+  const char *const saltchars =
     "./0123456789ABCDEFGHIJKLMNOPQRST"
     "UVWXYZabcdefghijklmnopqrstuvwxyz";
   char *password;
   int i;
 
-  /* Generate a (not very) random seed.
-     You should do it better than this...  */
-  seed[0] = time(NULL);
-  seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
-
-  /* Turn it into printable characters from `seedchars'.  */
-  for (i = 0; i < 8; i++)
-    salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
+  /* Retrieve 16 unpredictable bytes from the operating system.  */
+  if (getentropy (ubytes, sizeof ubytes))
+    {
+      perror ("getentropy");
+      return 1;
+    }
+
+  /* Use them to fill in the salt string.  */
+  salt[0] = '$';
+  salt[1] = '5'; /* SHA-256 */
+  salt[2] = '$';
+  for (i = 0; i < 16; i++)
+    salt[3+i] = saltchars[ubytes[i] & 0x3f];
+  salt[19] = '\0';
 
   /* Read in the user's password and encrypt it.  */
-  password = crypt(getpass("Password:"), salt);
+  password = crypt (getpass ("Password:"), salt);
+  if (!password)
+    {
+      perror ("crypt");
+      return 1;
+    }
 
   /* Print the results.  */
-  puts(password);
+  puts (password);
   return 0;
 }
diff --git a/manual/examples/testpass.c b/manual/examples/testpass.c
index 19f1ae7de0..3cc2383ea8 100644
--- a/manual/examples/testpass.c
+++ b/manual/examples/testpass.c
@@ -15,29 +15,45 @@
    along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <sys/types.h>
+#include <pwd.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <crypt.h>
 
 int
-main(void)
+main(int argc, char **argv)
 {
-  /* Hashed form of "GNU libc manual".  */
-  const char *const pass = "$1$/iSaq7rB$EoUw5jJPPvAPECNaaWzMK/";
-
   char *result;
   int ok;
+  struct passwd *pw;
+
+  if (argc < 2)
+    {
+      fprintf (stderr, "usage: %s username\n", argv[0]);
+      return 1;
+    }
+
+  /* Retrieve the password for user argv[1]
+     from the user database.  */
+  pw = getpwnam (argv[1]);
 
-/*@group*/
   /* Read in the user's password and encrypt it,
      passing the expected password in as the salt.  */
-  result = crypt(getpass("Password:"), pass);
-/*@end group*/
+  result = crypt (getpass ("Password:"), pw->pw_passwd);
+  if (!result)
+    {
+      perror ("crypt");
+      return 1;
+    }
+
+  printf ("Stored:  %s\n", pw->pw_passwd);
+  printf ("Current: %s\n", result);
 
   /* Test the result.  */
-  ok = strcmp (result, pass) == 0;
+  ok = strcmp (result, pw->pw_passwd) == 0;
 
-  puts(ok ? "Access granted." : "Access denied.");
+  puts (ok ? "Access granted." : "Access denied.");
   return ok ? 0 : 1;
 }
diff --git a/manual/random.texi b/manual/random.texi
index c53ed7fc22..c68a43aca0 100644
--- a/manual/random.texi
+++ b/manual/random.texi
@@ -2,6 +2,52 @@
 @chapter Random Number Generation
 @c %MENU% Various ways to generate random values.
 
+Many algorithms require a source of @dfn{random numbers}, or to be
+more precise, sequences of numbers chosen uniformly at random from
+some subset of the integers or reals.  There are several different
+ways to generate random numbers, depending on how stringent your
+requirements are.
+
+A @dfn{pseudo-random number generator} (PRNG) produces a sequence of
+numbers that @emph{appears} to be random, and has statistical
+properties matching what we expect of numbers chosen uniformly at
+random.  However, an ordinary PRNG doesn't guarantee that its output
+is unguessable.  Also, the output of a PRNG depends on a relatively
+small @dfn{seed} value, and so there are only a small number of
+sequences that it can produce; astronomically small, relative to the
+total number of random sequences.  If the seed is reused, the output
+will be exactly the same, which is sometimes exactly what you want,
+and sometimes disastrous.
+
+A @dfn{cryptographically strong pseudo-random number generator}
+(CSPRNG) is a PRNG that @emph{does} guarantee its output is
+unguessable.  Formally, there is no deterministic, polynomial-time
+algorithm@footnote{Assuming
+@iftex
+@c Don't typeset NP as if multiplying N by P. Use text italic for both.
+@math{\hbox{\it P} \neq \hbox{\it NP}}@c
+@end iftex
+@ifnottex
+@math{P ≠ NP}@c
+@end ifnottex
+.} that can tell the difference between the output of
+a CSPRNG and a sequence of numbers that really were chosen uniformly
+at random.  A CSPRNG still uses a seed and can only produce an
+astronomically small number of random sequences.
+
+Finally, a @dfn{true random number generator} (TRNG) produces random
+numbers not from a seed, but from some unpredictable physical process.
+In principle, a TRNG's output is unguessable, and is not limited to an
+astronomically small number of sequences.  However, TRNGs are very
+slow, and because there is no seed, there is no way to make one repeat
+its output.  Usually, it is best to use a TRNG only to choose the seed
+for a PRNG or CSPRNG.
+
+At present, @theglibc{} offers a variety of ordinary PRNGs, and on
+some operating systems it also offers access to an OS-provided TRNG.
+We may add a CSPRNG in the future.
+
+
 @menu
 * Pseudo-Random Numbers::       Sequences of numbers with apparently
                                  random distribution, but not difficult
@@ -30,8 +76,7 @@ is convenient when you are debugging a program, but it is unhelpful if
 you want the program to behave unpredictably.  If you want a different
 pseudo-random series each time your program runs, you must specify a
 different seed each time.  For ordinary purposes, basing the seed on the
-current time works well.  For random numbers in cryptography,
-@pxref{Unpredictable Bytes}.
+current time works well.
 
 You can obtain repeatable sequences of numbers on a particular machine type
 by specifying the same initial seed value for the random number
@@ -595,14 +640,18 @@ programs.
 @node Unpredictable Bytes
 @section Generating Unpredictable Bytes
 
-Some cryptographic applications (such as session key generation) need
-unpredictable bytes.
+Some cryptographic applications need truly unpredictable bytes.
+@Theglibc{} provides two functions for this purpose, both of which
+access a true random generator implemented by the operating system.
+Not all operating systems support these functions; programs that use
+them must be prepared for them to fail.  They are slow, and can only
+produce short sequences of unpredictable bytes.  Most programs should
+use these functions only to seed a cryptographically strong
+pseudo-random generator.
 
-In general, application code should use a deterministic random bit
-generator, which could call the @code{getentropy} function described
-below internally to obtain randomness to seed the generator.  The
-@code{getrandom} function is intended for low-level applications which
-need additional control over the blocking behavior.
+Most programs should use @code{getentropy}.  The @code{getrandom}
+function is intended for low-level applications which need additional
+control over the blocking behavior.
 
 @deftypefun int getentropy (void *@var{buffer}, size_t @var{length})
 @standards{GNU, sys/random.h}
@@ -623,7 +672,9 @@ will keep blocking even if a signal arrives, and return only after the
 entropy pool has been initialized.
 
 The @code{getentropy} function can fail with several errors, some of
-which are listed below.
+which are listed below.  Applications must check for failure.
+However, when it succeeds, it will always produce exactly @var{length}
+bytes of random data.
 
 @table @code
 @item ENOSYS
@@ -645,11 +696,11 @@ could not be overwritten with random data for an unspecified reason.
 @standards{GNU, sys/random.h}
 @safety{@mtsafe{}@assafe{}@acsafe{}}
 
-This function writes @var{length} bytes of random data to the array
-starting at @var{buffer}.  On success, this function returns the number
-of bytes which have been written to the buffer (which can be less than
-@var{length}).  On error, @code{-1} is returned, and @code{errno} is
-updated accordingly.
+This function writes up to @var{length} bytes of random data to the
+array starting at @var{buffer}.  On success, this function returns the
+number of bytes which have been written to the buffer, which can be
+less than @var{length}.  On error, @code{-1} is returned, and
+@code{errno} is updated accordingly.
 
 The @code{getrandom} function is declared in the header file
 @file{sys/random.h}.  It is a GNU extension.
@@ -676,7 +727,8 @@ booted and the pool has not yet been initialized.
 
 The @code{getrandom} function can fail with several errors, some of
 which are listed below.  In addition, the function may not fill the
-buffer completely and return a value less than @var{length}.
+buffer completely.  Applications must check for failure and for short
+writes.
 
 @table @code
 @item ENOSYS
diff --git a/manual/string.texi b/manual/string.texi
index b07cfb4550..f113777f2d 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -2469,8 +2469,6 @@ Unlike Rot13, @code{memfrob} works on arbitrary binary data, not just
 text.
 @cindex Rot13
 
-For true encryption, @xref{Cryptographic Functions}.
-
 This function is declared in @file{string.h}.
 @pindex string.h
 
@@ -2487,9 +2485,7 @@ Note that @code{memfrob} a second time on the same data structure
 returns it to its original state.
 
 This is a good function for hiding information from someone who doesn't
-want to see it or doesn't want to see it very much.  To really prevent
-people from retrieving the information, use stronger encryption such as
-that described in @xref{Cryptographic Functions}.
+want to see it or doesn't want to see it very much.
 
 @strong{Portability Note:}  This function is unique to @theglibc{}.
 
-- 
2.17.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/4] Reorganize manual sections on cryptography and random numbers.
  2018-05-06 17:52 [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Zack Weinberg
                   ` (2 preceding siblings ...)
  2018-05-06 17:52 ` [PATCH 4/4] New configure option --disable-crypt Zack Weinberg
@ 2018-05-06 17:52 ` Zack Weinberg
  2018-05-08 13:29   ` Florian Weimer
  2018-05-09 11:36   ` Rical Jasan
  2018-05-08 22:56 ` [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Rical Jasan
  4 siblings, 2 replies; 19+ messages in thread
From: Zack Weinberg @ 2018-05-06 17:52 UTC (permalink / raw)
  To: libc-alpha; +Cc: carlos, fweimer, rj

In preparation for improvements to the discussion of cryptography,
password handling, and random number generation, reorganize the
sections of the manual that deal with these topics.  This patch
neither deletes any old text nor introduces any new text; it only
moves text around.  The description of 'getpass' moves to
terminal.texi, since all it does is read a password from the
controlling terminal with echo disabled.  The pseudo-random number
generator sections from math.texi and the "Unpredictable Bytes"
section of crypt.texi are moved to a new file random.texi.  Also, it
is no longer true that crypt.texi's top @node needs to have no pointers.

	* manual/crypt.texi: Move most of the introductory text to the
        'crypt' section.  Move the example programs below the
        @deftypefun for 'crypt_r'.  Move the DESERR_* table and
        DES_FAILED deftypefun below cbc_crypt.  Move the entire
        'getpass' section...
	* manual/terminal.texi: ...here.

	* manual/random.texi: New file consolidating all discussion of
	random number generation.
	* manual/crypt.texi: 'Unpredictable Bytes' section moved to random.texi.
	* manual/math.texi: 'Pseudo-Random Numbers' section moved to
	random.texi.
	* manual/Makefile (chapters): Add 'random' after 'arith'.
	* manual/arith.texi, manual/time.texi: Update chapter-level node
	pointers.
---
 manual/Makefile      |   2 +-
 manual/arith.texi    |   2 +-
 manual/crypt.texi    | 301 +++++--------------
 manual/math.texi     | 586 +-----------------------------------
 manual/random.texi   | 702 +++++++++++++++++++++++++++++++++++++++++++
 manual/terminal.texi |  45 +++
 manual/time.texi     |   2 +-
 7 files changed, 823 insertions(+), 817 deletions(-)
 create mode 100644 manual/random.texi

diff --git a/manual/Makefile b/manual/Makefile
index c2756640a7..99689c3182 100644
--- a/manual/Makefile
+++ b/manual/Makefile
@@ -36,7 +36,7 @@ endif
 chapters = $(addsuffix .texi, \
 		       intro errno memory ctype string charset locale	\
 		       message search pattern io stdio llio filesys	\
-		       pipe socket terminal syslog math arith time	\
+		       pipe socket terminal syslog math arith random time \
 		       resource setjmp signal startup process ipc job	\
 		       nss users sysinfo conf crypt debug threads	\
 		       probes tunables)
diff --git a/manual/arith.texi b/manual/arith.texi
index 116788ba9a..fe4bf9bd0d 100644
--- a/manual/arith.texi
+++ b/manual/arith.texi
@@ -1,4 +1,4 @@
-@node Arithmetic, Date and Time, Mathematics, Top
+@node Arithmetic, Random Number Generation, Mathematics, Top
 @c %MENU% Low level arithmetic functions
 @chapter Arithmetic Functions
 
diff --git a/manual/crypt.texi b/manual/crypt.texi
index 99d2d8e092..c24306c07c 100644
--- a/manual/crypt.texi
+++ b/manual/crypt.texi
@@ -1,34 +1,6 @@
-@c This node must have no pointers.
-@node Cryptographic Functions
-@c @node Cryptographic Functions, Debugging Support, System Configuration, Top
-@chapter DES Encryption and Password Handling
-@c %MENU% DES encryption and password handling
-
-On many systems, it is unnecessary to have any kind of user
-authentication; for instance, a workstation which is not connected to a
-network probably does not need any user authentication, because to use
-the machine an intruder must have physical access.
-
-Sometimes, however, it is necessary to be sure that a user is authorized
-to use some service a machine provides---for instance, to log in as a
-particular user id (@pxref{Users and Groups}).  One traditional way of
-doing this is for each user to choose a secret @dfn{password}; then, the
-system can ask someone claiming to be a user what the user's password
-is, and if the person gives the correct password then the system can
-grant the appropriate privileges.
-
-If all the passwords are just stored in a file somewhere, then this file
-has to be very carefully protected.  To avoid this, passwords are run
-through a @dfn{one-way function}, a function which makes it difficult to
-work out what its input was by looking at its output, before storing in
-the file.
-
-@Theglibc{} provides a one-way function that is compatible with
-the behavior of the @code{crypt} function introduced in FreeBSD 2.0.
-It supports two one-way algorithms: one based on the MD5
-message-digest algorithm that is compatible with modern BSD systems,
-and the other based on the Data Encryption Standard (DES) that is
-compatible with Unix systems.
+@node Cryptographic Functions, Debugging Support, System Configuration, Top
+@chapter Cryptographic Functions
+@c %MENU% Password storage and obsolete encryption functions
 
 @vindex AUTH_DES
 @cindex FIPS 140-2
@@ -42,10 +14,8 @@ encrypted authentication use normal DES.
 
 @menu
 * Legal Problems::              This software can get you locked up, or worse.
-* getpass::                     Prompting the user for a password.
 * crypt::                       A one-way function for passwords.
 * DES Encryption::              Routines for DES encryption.
-* Unpredictable Bytes::         Randomness for cryptography purposes.
 @end menu
 
 @node Legal Problems
@@ -90,53 +60,34 @@ The rules in this area are continuously changing.  If you know of any
 information in this manual that is out-of-date, please report it to
 the bug database.  @xref{Reporting Bugs}.
 
-@node getpass
-@section Reading Passwords
-
-When reading in a password, it is desirable to avoid displaying it on
-the screen, to help keep it secret.  The following function handles this
-in a convenient way.
-
-@deftypefun {char *} getpass (const char *@var{prompt})
-@standards{BSD, unistd.h}
-@safety{@prelim{}@mtunsafe{@mtasuterm{}}@asunsafe{@ascuheap{} @asulock{} @asucorrupt{}}@acunsafe{@acuterm{} @aculock{} @acucorrupt{}}}
-@c This function will attempt to create a stream for terminal I/O, but
-@c will fallback to stdio/stderr.  It attempts to change the terminal
-@c mode in a thread-unsafe way, write out the prompt, read the password,
-@c then restore the terminal mode.  It has a cleanup to close the stream
-@c in case of (synchronous) cancellation, but not to restore the
-@c terminal mode.
-
-@code{getpass} outputs @var{prompt}, then reads a string in from the
-terminal without echoing it.  It tries to connect to the real terminal,
-@file{/dev/tty}, if possible, to encourage users not to put plaintext
-passwords in files; otherwise, it uses @code{stdin} and @code{stderr}.
-@code{getpass} also disables the INTR, QUIT, and SUSP characters on the
-terminal using the @code{ISIG} terminal attribute (@pxref{Local Modes}).
-The terminal is flushed before and after @code{getpass}, so that
-characters of a mistyped password are not accidentally visible.
-
-In other C libraries, @code{getpass} may only return the first
-@code{PASS_MAX} bytes of a password.  @Theglibc{} has no limit, so
-@code{PASS_MAX} is undefined.
-
-The prototype for this function is in @file{unistd.h}.  @code{PASS_MAX}
-would be defined in @file{limits.h}.
-@end deftypefun
+@node crypt
+@section Encrypting Passwords
 
-This precise set of operations may not suit all possible situations.  In
-this case, it is recommended that users write their own @code{getpass}
-substitute.  For instance, a very simple substitute is as follows:
+On many systems, it is unnecessary to have any kind of user
+authentication; for instance, a workstation which is not connected to a
+network probably does not need any user authentication, because to use
+the machine an intruder must have physical access.
 
-@smallexample
-@include mygetpass.c.texi
-@end smallexample
+Sometimes, however, it is necessary to be sure that a user is authorized
+to use some service a machine provides---for instance, to log in as a
+particular user id (@pxref{Users and Groups}).  One traditional way of
+doing this is for each user to choose a secret @dfn{password}; then, the
+system can ask someone claiming to be a user what the user's password
+is, and if the person gives the correct password then the system can
+grant the appropriate privileges.
 
-The substitute takes the same parameters as @code{getline}
-(@pxref{Line Input}); the user must print any prompt desired.
+If all the passwords are just stored in a file somewhere, then this file
+has to be very carefully protected.  To avoid this, passwords are run
+through a @dfn{one-way function}, a function which makes it difficult to
+work out what its input was by looking at its output, before storing in
+the file.
 
-@node crypt
-@section Encrypting Passwords
+@Theglibc{} provides a one-way function that is compatible with
+the behavior of the @code{crypt} function introduced in FreeBSD 2.0.
+It supports two one-way algorithms: one based on the MD5
+message-digest algorithm that is compatible with modern BSD systems,
+and the other based on the Data Encryption Standard (DES) that is
+compatible with Unix systems.
 
 @deftypefun {char *} crypt (const char *@var{key}, const char *@var{salt})
 @standards{BSD, crypt.h}
@@ -188,6 +139,23 @@ password against the result of a previous call to @code{crypt}, pass
 the result of the previous call as the @var{salt}.
 @end deftypefun
 
+@deftypefun {char *} crypt_r (const char *@var{key}, const char *@var{salt}, {struct crypt_data *} @var{data})
+@standards{GNU, crypt.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
+@c Compared with crypt, this function fixes the @mtasurace:crypt
+@c problem, but nothing else.
+
+The @code{crypt_r} function does the same thing as @code{crypt}, but
+takes an extra parameter which includes space for its result (among
+other things), so it can be reentrant.  @code{data@w{->}initialized} must be
+cleared to zero before the first time @code{crypt_r} is called.
+
+The @code{crypt_r} function is a GNU extension.
+@end deftypefun
+
+The @code{crypt} and @code{crypt_r} functions are prototyped in the
+header @file{crypt.h}.
+
 The following short program is an example of how to use @code{crypt} the
 first time a password is entered.  Note that the @var{salt} generation
 is just barely acceptable; in particular, it is not unique between
@@ -206,23 +174,6 @@ for a password and prints ``Access granted.'' if the user types
 @include testpass.c.texi
 @end smallexample
 
-@deftypefun {char *} crypt_r (const char *@var{key}, const char *@var{salt}, {struct crypt_data *} @var{data})
-@standards{GNU, crypt.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
-@c Compared with crypt, this function fixes the @mtasurace:crypt
-@c problem, but nothing else.
-
-The @code{crypt_r} function does the same thing as @code{crypt}, but
-takes an extra parameter which includes space for its result (among
-other things), so it can be reentrant.  @code{data@w{->}initialized} must be
-cleared to zero before the first time @code{crypt_r} is called.
-
-The @code{crypt_r} function is a GNU extension.
-@end deftypefun
-
-The @code{crypt} and @code{crypt_r} functions are prototyped in the
-header @file{crypt.h}.
-
 @node DES Encryption
 @section DES Encryption
 
@@ -345,33 +296,6 @@ This constant, used in the @var{mode} parameter, specifies that no
 hardware device is to be used.
 @end vtable
 
-The result of the function will be one of these values:
-
-@vtable @code
-@item DESERR_NONE
-@standards{SUNRPC, rpc/des_crypt.h}
-The encryption succeeded.
-
-@item DESERR_NOHWDEVICE
-@standards{SUNRPC, rpc/des_crypt.h}
-The encryption succeeded, but there was no hardware device available.
-
-@item DESERR_HWERROR
-@standards{SUNRPC, rpc/des_crypt.h}
-The encryption failed because of a hardware problem.
-
-@item DESERR_BADPARAM
-@standards{SUNRPC, rpc/des_crypt.h}
-The encryption failed because of a bad parameter, for instance @var{len}
-is not a multiple of 8 or @var{len} is larger than @code{DES_MAXDATA}.
-@end vtable
-@end deftypefun
-
-@deftypefun int DES_FAILED (int @var{err})
-@standards{SUNRPC, rpc/des_crypt.h}
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-This macro returns 1 if @var{err} is a `success' result code from
-@code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
 @end deftypefun
 
 @deftypefun int cbc_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode}, char *@var{ivec})
@@ -400,6 +324,34 @@ bytes.
 Otherwise, all the parameters are similar to those for @code{ecb_crypt}.
 @end deftypefun
 
+The result of the function will be one of these values:
+
+@vtable @code
+@item DESERR_NONE
+@standards{SUNRPC, rpc/des_crypt.h}
+The encryption succeeded.
+
+@item DESERR_NOHWDEVICE
+@standards{SUNRPC, rpc/des_crypt.h}
+The encryption succeeded, but there was no hardware device available.
+
+@item DESERR_HWERROR
+@standards{SUNRPC, rpc/des_crypt.h}
+The encryption failed because of a hardware problem.
+
+@item DESERR_BADPARAM
+@standards{SUNRPC, rpc/des_crypt.h}
+The encryption failed because of a bad parameter, for instance @var{len}
+is not a multiple of 8 or @var{len} is larger than @code{DES_MAXDATA}.
+@end vtable
+
+@deftypefun int DES_FAILED (int @var{err})
+@standards{SUNRPC, rpc/des_crypt.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+This macro returns 1 if @var{err} is a `success' result code from
+@code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
+@end deftypefun
+
 @deftypefun void des_setparity (char *@var{key})
 @standards{SUNRPC, rpc/des_crypt.h}
 @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
@@ -412,112 +364,3 @@ each byte.
 The @code{ecb_crypt}, @code{cbc_crypt}, and @code{des_setparity}
 functions and their accompanying macros are all defined in the header
 @file{rpc/des_crypt.h}.
-
-@node Unpredictable Bytes
-@section Generating Unpredictable Bytes
-
-Some cryptographic applications (such as session key generation) need
-unpredictable bytes.
-
-In general, application code should use a deterministic random bit
-generator, which could call the @code{getentropy} function described
-below internally to obtain randomness to seed the generator.  The
-@code{getrandom} function is intended for low-level applications which
-need additional control over the blocking behavior.
-
-@deftypefun int getentropy (void *@var{buffer}, size_t @var{length})
-@standards{GNU, sys/random.h}
-@safety{@mtsafe{}@assafe{}@acsafe{}}
-
-This function writes @var{length} bytes of random data to the array
-starting at @var{buffer}, which must be at most 256 bytes long.  The
-function returns zero on success.  On failure, it returns @code{-1} and
-@code{errno} is updated accordingly.
-
-The @code{getentropy} function is declared in the header file
-@file{sys/random.h}.  It is derived from OpenBSD.
-
-The @code{getentropy} function is not a cancellation point.  A call to
-@code{getentropy} can block if the system has just booted and the kernel
-entropy pool has not yet been initialized.  In this case, the function
-will keep blocking even if a signal arrives, and return only after the
-entropy pool has been initialized.
-
-The @code{getentropy} function can fail with several errors, some of
-which are listed below.
-
-@table @code
-@item ENOSYS
-The kernel does not implement the required system call.
-
-@item EFAULT
-The combination of @var{buffer} and @var{length} arguments specifies
-an invalid memory range.
-
-@item EIO
-More than 256 bytes of randomness have been requested, or the buffer
-could not be overwritten with random data for an unspecified reason.
-
-@end table
-
-@end deftypefun
-
-@deftypefun ssize_t getrandom (void *@var{buffer}, size_t @var{length}, unsigned int @var{flags})
-@standards{GNU, sys/random.h}
-@safety{@mtsafe{}@assafe{}@acsafe{}}
-
-This function writes @var{length} bytes of random data to the array
-starting at @var{buffer}.  On success, this function returns the number
-of bytes which have been written to the buffer (which can be less than
-@var{length}).  On error, @code{-1} is returned, and @code{errno} is
-updated accordingly.
-
-The @code{getrandom} function is declared in the header file
-@file{sys/random.h}.  It is a GNU extension.
-
-The following flags are defined for the @var{flags} argument:
-
-@table @code
-@item GRND_RANDOM
-Use the @file{/dev/random} (blocking) pool instead of the
-@file{/dev/urandom} (non-blocking) pool to obtain randomness.  If the
-@code{GRND_RANDOM} flag is specified, the @code{getrandom} function can
-block even after the randomness source has been initialized.
-
-@item GRND_NONBLOCK
-Instead of blocking, return to the caller immediately if no data is
-available.
-@end table
-
-The @code{getrandom} function is a cancellation point.
-
-Obtaining randomness from the @file{/dev/urandom} pool (i.e., a call
-without the @code{GRND_RANDOM} flag) can block if the system has just
-booted and the pool has not yet been initialized.
-
-The @code{getrandom} function can fail with several errors, some of
-which are listed below.  In addition, the function may not fill the
-buffer completely and return a value less than @var{length}.
-
-@table @code
-@item ENOSYS
-The kernel does not implement the @code{getrandom} system call.
-
-@item EAGAIN
-No random data was available and @code{GRND_NONBLOCK} was specified in
-@var{flags}.
-
-@item EFAULT
-The combination of @var{buffer} and @var{length} arguments specifies
-an invalid memory range.
-
-@item EINTR
-The system call was interrupted.  During the system boot process, before
-the kernel randomness pool is initialized, this can happen even if
-@var{flags} is zero.
-
-@item EINVAL
-The @var{flags} argument contains an invalid combination of flags.
-@end table
-
-@end deftypefun
diff --git a/manual/math.texi b/manual/math.texi
index d19a14b47d..776db62d1e 100644
--- a/manual/math.texi
+++ b/manual/math.texi
@@ -28,7 +28,7 @@
 @end ifclear
 
 @node Mathematics, Arithmetic, Syslog, Top
-@c %MENU% Math functions, useful constants, random numbers
+@c %MENU% Math functions, useful constants
 @chapter Mathematics
 
 This chapter contains information about functions for performing
@@ -81,8 +81,6 @@ aarch64, alpha, mips64, riscv, s390 and sparc.
 * Hyperbolic Functions::        sinh, cosh, tanh, etc.
 * Special Functions::           Bessel, gamma, erf.
 * Errors in Math Functions::    Known Maximum Errors in Math Functions.
-* Pseudo-Random Numbers::       Functions for generating pseudo-random
-				 numbers.
 * FP Function Optimizations::   Fast code or small code.
 @end menu
 
@@ -1401,588 +1399,6 @@ Functions not listed do not have known errors.
 @c This multitable does not fit on a single page
 @include libm-err.texi
 
-@node Pseudo-Random Numbers
-@section Pseudo-Random Numbers
-@cindex random numbers
-@cindex pseudo-random numbers
-@cindex seed (for random numbers)
-
-This section describes the GNU facilities for generating a series of
-pseudo-random numbers.  The numbers generated are not truly random;
-typically, they form a sequence that repeats periodically, with a period
-so large that you can ignore it for ordinary purposes.  The random
-number generator works by remembering a @dfn{seed} value which it uses
-to compute the next random number and also to compute a new seed.
-
-Although the generated numbers look unpredictable within one run of a
-program, the sequence of numbers is @emph{exactly the same} from one run
-to the next.  This is because the initial seed is always the same.  This
-is convenient when you are debugging a program, but it is unhelpful if
-you want the program to behave unpredictably.  If you want a different
-pseudo-random series each time your program runs, you must specify a
-different seed each time.  For ordinary purposes, basing the seed on the
-current time works well.  For random numbers in cryptography,
-@pxref{Unpredictable Bytes}.
-
-You can obtain repeatable sequences of numbers on a particular machine type
-by specifying the same initial seed value for the random number
-generator.  There is no standard meaning for a particular seed value;
-the same seed, used in different C libraries or on different CPU types,
-will give you different random numbers.
-
-@Theglibc{} supports the standard @w{ISO C} random number functions
-plus two other sets derived from BSD and SVID.  The BSD and @w{ISO C}
-functions provide identical, somewhat limited functionality.  If only a
-small number of random bits are required, we recommend you use the
-@w{ISO C} interface, @code{rand} and @code{srand}.  The SVID functions
-provide a more flexible interface, which allows better random number
-generator algorithms, provides more random bits (up to 48) per call, and
-can provide random floating-point numbers.  These functions are required
-by the XPG standard and therefore will be present in all modern Unix
-systems.
-
-@menu
-* ISO Random::                  @code{rand} and friends.
-* BSD Random::                  @code{random} and friends.
-* SVID Random::                 @code{drand48} and friends.
-@end menu
-
-@node ISO Random
-@subsection ISO C Random Number Functions
-
-This section describes the random number functions that are part of
-the @w{ISO C} standard.
-
-To use these facilities, you should include the header file
-@file{stdlib.h} in your program.
-@pindex stdlib.h
-
-@deftypevr Macro int RAND_MAX
-@standards{ISO, stdlib.h}
-The value of this macro is an integer constant representing the largest
-value the @code{rand} function can return.  In @theglibc{}, it is
-@code{2147483647}, which is the largest signed integer representable in
-32 bits.  In other libraries, it may be as low as @code{32767}.
-@end deftypevr
-
-@deftypefun int rand (void)
-@standards{ISO, stdlib.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
-@c Just calls random.
-The @code{rand} function returns the next pseudo-random number in the
-series.  The value ranges from @code{0} to @code{RAND_MAX}.
-@end deftypefun
-
-@deftypefun void srand (unsigned int @var{seed})
-@standards{ISO, stdlib.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
-@c Alias to srandom.
-This function establishes @var{seed} as the seed for a new series of
-pseudo-random numbers.  If you call @code{rand} before a seed has been
-established with @code{srand}, it uses the value @code{1} as a default
-seed.
-
-To produce a different pseudo-random series each time your program is
-run, do @code{srand (time (0))}.
-@end deftypefun
-
-POSIX.1 extended the C standard functions to support reproducible random
-numbers in multi-threaded programs.  However, the extension is badly
-designed and unsuitable for serious work.
-
-@deftypefun int rand_r (unsigned int *@var{seed})
-@standards{POSIX.1, stdlib.h}
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-This function returns a random number in the range 0 to @code{RAND_MAX}
-just as @code{rand} does.  However, all its state is stored in the
-@var{seed} argument.  This means the RNG's state can only have as many
-bits as the type @code{unsigned int} has.  This is far too few to
-provide a good RNG.
-
-If your program requires a reentrant RNG, we recommend you use the
-reentrant GNU extensions to the SVID random number generator.  The
-POSIX.1 interface should only be used when the GNU extensions are not
-available.
-@end deftypefun
-
-
-@node BSD Random
-@subsection BSD Random Number Functions
-
-This section describes a set of random number generation functions that
-are derived from BSD.  There is no advantage to using these functions
-with @theglibc{}; we support them for BSD compatibility only.
-
-The prototypes for these functions are in @file{stdlib.h}.
-@pindex stdlib.h
-
-@deftypefun {long int} random (void)
-@standards{BSD, stdlib.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
-@c Takes a lock and calls random_r with an automatic variable and the
-@c global state, while holding a lock.
-This function returns the next pseudo-random number in the sequence.
-The value returned ranges from @code{0} to @code{2147483647}.
-
-@strong{NB:} Temporarily this function was defined to return a
-@code{int32_t} value to indicate that the return value always contains
-32 bits even if @code{long int} is wider.  The standard demands it
-differently.  Users must always be aware of the 32-bit limitation,
-though.
-@end deftypefun
-
-@deftypefun void srandom (unsigned int @var{seed})
-@standards{BSD, stdlib.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
-@c Takes a lock and calls srandom_r with an automatic variable and a
-@c static buffer.  There's no MT-safety issue because the static buffer
-@c is internally protected by a lock, although other threads may modify
-@c the set state before it is used.
-The @code{srandom} function sets the state of the random number
-generator based on the integer @var{seed}.  If you supply a @var{seed} value
-of @code{1}, this will cause @code{random} to reproduce the default set
-of random numbers.
-
-To produce a different set of pseudo-random numbers each time your
-program runs, do @code{srandom (time (0))}.
-@end deftypefun
-
-@deftypefun {char *} initstate (unsigned int @var{seed}, char *@var{state}, size_t @var{size})
-@standards{BSD, stdlib.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
-The @code{initstate} function is used to initialize the random number
-generator state.  The argument @var{state} is an array of @var{size}
-bytes, used to hold the state information.  It is initialized based on
-@var{seed}.  The size must be between 8 and 256 bytes, and should be a
-power of two.  The bigger the @var{state} array, the better.
-
-The return value is the previous value of the state information array.
-You can use this value later as an argument to @code{setstate} to
-restore that state.
-@end deftypefun
-
-@deftypefun {char *} setstate (char *@var{state})
-@standards{BSD, stdlib.h}
-@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
-The @code{setstate} function restores the random number state
-information @var{state}.  The argument must have been the result of
-a previous call to @var{initstate} or @var{setstate}.
-
-The return value is the previous value of the state information array.
-You can use this value later as an argument to @code{setstate} to
-restore that state.
-
-If the function fails the return value is @code{NULL}.
-@end deftypefun
-
-The four functions described so far in this section all work on a state
-which is shared by all threads.  The state is not directly accessible to
-the user and can only be modified by these functions.  This makes it
-hard to deal with situations where each thread should have its own
-pseudo-random number generator.
-
-@Theglibc{} contains four additional functions which contain the
-state as an explicit parameter and therefore make it possible to handle
-thread-local PRNGs.  Besides this there is no difference.  In fact, the
-four functions already discussed are implemented internally using the
-following interfaces.
-
-The @file{stdlib.h} header contains a definition of the following type:
-
-@deftp {Data Type} {struct random_data}
-@standards{GNU, stdlib.h}
-
-Objects of type @code{struct random_data} contain the information
-necessary to represent the state of the PRNG.  Although a complete
-definition of the type is present the type should be treated as opaque.
-@end deftp
-
-The functions modifying the state follow exactly the already described
-functions.
-
-@deftypefun int random_r (struct random_data *restrict @var{buf}, int32_t *restrict @var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{random_r} function behaves exactly like the @code{random}
-function except that it uses and modifies the state in the object
-pointed to by the first parameter instead of the global state.
-@end deftypefun
-
-@deftypefun int srandom_r (unsigned int @var{seed}, struct random_data *@var{buf})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{srandom_r} function behaves exactly like the @code{srandom}
-function except that it uses and modifies the state in the object
-pointed to by the second parameter instead of the global state.
-@end deftypefun
-
-@deftypefun int initstate_r (unsigned int @var{seed}, char *restrict @var{statebuf}, size_t @var{statelen}, struct random_data *restrict @var{buf})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{initstate_r} function behaves exactly like the @code{initstate}
-function except that it uses and modifies the state in the object
-pointed to by the fourth parameter instead of the global state.
-@end deftypefun
-
-@deftypefun int setstate_r (char *restrict @var{statebuf}, struct random_data *restrict @var{buf})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{setstate_r} function behaves exactly like the @code{setstate}
-function except that it uses and modifies the state in the object
-pointed to by the first parameter instead of the global state.
-@end deftypefun
-
-@node SVID Random
-@subsection SVID Random Number Function
-
-The C library on SVID systems contains yet another kind of random number
-generator functions.  They use a state of 48 bits of data.  The user can
-choose among a collection of functions which return the random bits
-in different forms.
-
-Generally there are two kinds of function.  The first uses a state of
-the random number generator which is shared among several functions and
-by all threads of the process.  The second requires the user to handle
-the state.
-
-All functions have in common that they use the same congruential
-formula with the same constants.  The formula is
-
-@smallexample
-Y = (a * X + c) mod m
-@end smallexample
-
-@noindent
-where @var{X} is the state of the generator at the beginning and
-@var{Y} the state at the end.  @code{a} and @code{c} are constants
-determining the way the generator works.  By default they are
-
-@smallexample
-a = 0x5DEECE66D = 25214903917
-c = 0xb = 11
-@end smallexample
-
-@noindent
-but they can also be changed by the user.  @code{m} is of course 2^48
-since the state consists of a 48-bit array.
-
-The prototypes for these functions are in @file{stdlib.h}.
-@pindex stdlib.h
-
-
-@deftypefun double drand48 (void)
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-@c Uses of the static state buffer are not guarded by a lock (thus
-@c @mtasurace:drand48), so they may be found or left at a
-@c partially-updated state in case of calls from within signal handlers
-@c or cancellation.  None of this will break safety rules or invoke
-@c undefined behavior, but it may affect randomness.
-This function returns a @code{double} value in the range of @code{0.0}
-to @code{1.0} (exclusive).  The random bits are determined by the global
-state of the random number generator in the C library.
-
-Since the @code{double} type according to @w{IEEE 754} has a 52-bit
-mantissa this means 4 bits are not initialized by the random number
-generator.  These are (of course) chosen to be the least significant
-bits and they are initialized to @code{0}.
-@end deftypefun
-
-@deftypefun double erand48 (unsigned short int @var{xsubi}[3])
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-@c The static buffer is just initialized with default parameters, which
-@c are later read to advance the state held in xsubi.
-This function returns a @code{double} value in the range of @code{0.0}
-to @code{1.0} (exclusive), similarly to @code{drand48}.  The argument is
-an array describing the state of the random number generator.
-
-This function can be called subsequently since it updates the array to
-guarantee random numbers.  The array should have been initialized before
-initial use to obtain reproducible results.
-@end deftypefun
-
-@deftypefun {long int} lrand48 (void)
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-The @code{lrand48} function returns an integer value in the range of
-@code{0} to @code{2^31} (exclusive).  Even if the size of the @code{long
-int} type can take more than 32 bits, no higher numbers are returned.
-The random bits are determined by the global state of the random number
-generator in the C library.
-@end deftypefun
-
-@deftypefun {long int} nrand48 (unsigned short int @var{xsubi}[3])
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-This function is similar to the @code{lrand48} function in that it
-returns a number in the range of @code{0} to @code{2^31} (exclusive) but
-the state of the random number generator used to produce the random bits
-is determined by the array provided as the parameter to the function.
-
-The numbers in the array are updated afterwards so that subsequent calls
-to this function yield different results (as is expected of a random
-number generator).  The array should have been initialized before the
-first call to obtain reproducible results.
-@end deftypefun
-
-@deftypefun {long int} mrand48 (void)
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-The @code{mrand48} function is similar to @code{lrand48}.  The only
-difference is that the numbers returned are in the range @code{-2^31} to
-@code{2^31} (exclusive).
-@end deftypefun
-
-@deftypefun {long int} jrand48 (unsigned short int @var{xsubi}[3])
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-The @code{jrand48} function is similar to @code{nrand48}.  The only
-difference is that the numbers returned are in the range @code{-2^31} to
-@code{2^31} (exclusive).  For the @code{xsubi} parameter the same
-requirements are necessary.
-@end deftypefun
-
-The internal state of the random number generator can be initialized in
-several ways.  The methods differ in the completeness of the
-information provided.
-
-@deftypefun void srand48 (long int @var{seedval})
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-The @code{srand48} function sets the most significant 32 bits of the
-internal state of the random number generator to the least
-significant 32 bits of the @var{seedval} parameter.  The lower 16 bits
-are initialized to the value @code{0x330E}.  Even if the @code{long
-int} type contains more than 32 bits only the lower 32 bits are used.
-
-Owing to this limitation, initialization of the state of this
-function is not very useful.  But it makes it easy to use a construct
-like @code{srand48 (time (0))}.
-
-A side-effect of this function is that the values @code{a} and @code{c}
-from the internal state, which are used in the congruential formula,
-are reset to the default values given above.  This is of importance once
-the user has called the @code{lcong48} function (see below).
-@end deftypefun
-
-@deftypefun {unsigned short int *} seed48 (unsigned short int @var{seed16v}[3])
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-The @code{seed48} function initializes all 48 bits of the state of the
-internal random number generator from the contents of the parameter
-@var{seed16v}.  Here the lower 16 bits of the first element of
-@var{seed16v} initialize the least significant 16 bits of the internal
-state, the lower 16 bits of @code{@var{seed16v}[1]} initialize the mid-order
-16 bits of the state and the 16 lower bits of @code{@var{seed16v}[2]}
-initialize the most significant 16 bits of the state.
-
-Unlike @code{srand48} this function lets the user initialize all 48 bits
-of the state.
-
-The value returned by @code{seed48} is a pointer to an array containing
-the values of the internal state before the change.  This might be
-useful to restart the random number generator at a certain state.
-Otherwise the value can simply be ignored.
-
-As for @code{srand48}, the values @code{a} and @code{c} from the
-congruential formula are reset to the default values.
-@end deftypefun
-
-There is one more function to initialize the random number generator
-which enables you to specify even more information by allowing you to
-change the parameters in the congruential formula.
-
-@deftypefun void lcong48 (unsigned short int @var{param}[7])
-@standards{SVID, stdlib.h}
-@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
-The @code{lcong48} function allows the user to change the complete state
-of the random number generator.  Unlike @code{srand48} and
-@code{seed48}, this function also changes the constants in the
-congruential formula.
-
-From the seven elements in the array @var{param} the least significant
-16 bits of the entries @code{@var{param}[0]} to @code{@var{param}[2]}
-determine the initial state, the least significant 16 bits of
-@code{@var{param}[3]} to @code{@var{param}[5]} determine the 48 bit
-constant @code{a} and @code{@var{param}[6]} determines the 16-bit value
-@code{c}.
-@end deftypefun
-
-All the above functions have in common that they use the global
-parameters for the congruential formula.  In multi-threaded programs it
-might sometimes be useful to have different parameters in different
-threads.  For this reason all the above functions have a counterpart
-which works on a description of the random number generator in the
-user-supplied buffer instead of the global state.
-
-Please note that it is no problem if several threads use the global
-state if all threads use the functions which take a pointer to an array
-containing the state.  The random numbers are computed following the
-same loop but if the state in the array is different all threads will
-obtain an individual random number generator.
-
-The user-supplied buffer must be of type @code{struct drand48_data}.
-This type should be regarded as opaque and not manipulated directly.
-
-@deftypefun int drand48_r (struct drand48_data *@var{buffer}, double *@var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-This function is equivalent to the @code{drand48} function with the
-difference that it does not modify the global random number generator
-parameters but instead the parameters in the buffer supplied through the
-pointer @var{buffer}.  The random number is returned in the variable
-pointed to by @var{result}.
-
-The return value of the function indicates whether the call succeeded.
-If the value is less than @code{0} an error occurred and @var{errno} is
-set to indicate the problem.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int erand48_r (unsigned short int @var{xsubi}[3], struct drand48_data *@var{buffer}, double *@var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{erand48_r} function works like @code{erand48}, but in addition
-it takes an argument @var{buffer} which describes the random number
-generator.  The state of the random number generator is taken from the
-@code{xsubi} array, the parameters for the congruential formula from the
-global random number generator data.  The random number is returned in
-the variable pointed to by @var{result}.
-
-The return value is non-negative if the call succeeded.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int lrand48_r (struct drand48_data *@var{buffer}, long int *@var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-This function is similar to @code{lrand48}, but in addition it takes a
-pointer to a buffer describing the state of the random number generator
-just like @code{drand48}.
-
-If the return value of the function is non-negative the variable pointed
-to by @var{result} contains the result.  Otherwise an error occurred.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int nrand48_r (unsigned short int @var{xsubi}[3], struct drand48_data *@var{buffer}, long int *@var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{nrand48_r} function works like @code{nrand48} in that it
-produces a random number in the range @code{0} to @code{2^31}.  But instead
-of using the global parameters for the congruential formula it uses the
-information from the buffer pointed to by @var{buffer}.  The state is
-described by the values in @var{xsubi}.
-
-If the return value is non-negative the variable pointed to by
-@var{result} contains the result.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int mrand48_r (struct drand48_data *@var{buffer}, long int *@var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-This function is similar to @code{mrand48} but like the other reentrant
-functions it uses the random number generator described by the value in
-the buffer pointed to by @var{buffer}.
-
-If the return value is non-negative the variable pointed to by
-@var{result} contains the result.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int jrand48_r (unsigned short int @var{xsubi}[3], struct drand48_data *@var{buffer}, long int *@var{result})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-The @code{jrand48_r} function is similar to @code{jrand48}.  Like the
-other reentrant functions of this function family it uses the
-congruential formula parameters from the buffer pointed to by
-@var{buffer}.
-
-If the return value is non-negative the variable pointed to by
-@var{result} contains the result.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-Before any of the above functions are used the buffer of type
-@code{struct drand48_data} should be initialized.  The easiest way to do
-this is to fill the whole buffer with null bytes, e.g. by
-
-@smallexample
-memset (buffer, '\0', sizeof (struct drand48_data));
-@end smallexample
-
-@noindent
-Using any of the reentrant functions of this family now will
-automatically initialize the random number generator to the default
-values for the state and the parameters of the congruential formula.
-
-The other possibility is to use any of the functions which explicitly
-initialize the buffer.  Though it might be obvious how to initialize the
-buffer from looking at the parameter to the function, it is highly
-recommended to use these functions since the result might not always be
-what you expect.
-
-@deftypefun int srand48_r (long int @var{seedval}, struct drand48_data *@var{buffer})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-The description of the random number generator represented by the
-information in @var{buffer} is initialized similarly to what the function
-@code{srand48} does.  The state is initialized from the parameter
-@var{seedval} and the parameters for the congruential formula are
-initialized to their default values.
-
-If the return value is non-negative the function call succeeded.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int seed48_r (unsigned short int @var{seed16v}[3], struct drand48_data *@var{buffer})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-This function is similar to @code{srand48_r} but like @code{seed48} it
-initializes all 48 bits of the state from the parameter @var{seed16v}.
-
-If the return value is non-negative the function call succeeded.  It
-does not return a pointer to the previous state of the random number
-generator like the @code{seed48} function does.  If the user wants to
-preserve the state for a later re-run s/he can copy the whole buffer
-pointed to by @var{buffer}.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
-@deftypefun int lcong48_r (unsigned short int @var{param}[7], struct drand48_data *@var{buffer})
-@standards{GNU, stdlib.h}
-@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
-This function initializes all aspects of the random number generator
-described in @var{buffer} with the data in @var{param}.  Here it is
-especially true that the function does more than just copying the
-contents of @var{param} and @var{buffer}.  More work is required and
-therefore it is important to use this function rather than initializing
-the random number generator directly.
-
-If the return value is non-negative the function call succeeded.
-
-This function is a GNU extension and should not be used in portable
-programs.
-@end deftypefun
-
 @node FP Function Optimizations
 @section Is Fast Code or Small Code preferred?
 @cindex Optimization
diff --git a/manual/random.texi b/manual/random.texi
new file mode 100644
index 0000000000..c53ed7fc22
--- /dev/null
+++ b/manual/random.texi
@@ -0,0 +1,702 @@
+@node Random Number Generation, Date and Time, Arithmetic, Top
+@chapter Random Number Generation
+@c %MENU% Various ways to generate random values.
+
+@menu
+* Pseudo-Random Numbers::       Sequences of numbers with apparently
+                                 random distribution, but not difficult
+                                 to predict.
+* Unpredictable Bytes::         Asking the operating system for truly
+				 unpredictable bytes.
+@end menu
+
+@node Pseudo-Random Numbers
+@section Pseudo-Random Numbers
+@cindex random numbers
+@cindex pseudo-random numbers
+@cindex seed (for random numbers)
+
+This section describes the GNU facilities for generating a series of
+pseudo-random numbers.  The numbers generated are not truly random;
+typically, they form a sequence that repeats periodically, with a period
+so large that you can ignore it for ordinary purposes.  The random
+number generator works by remembering a @dfn{seed} value which it uses
+to compute the next random number and also to compute a new seed.
+
+Although the generated numbers look unpredictable within one run of a
+program, the sequence of numbers is @emph{exactly the same} from one run
+to the next.  This is because the initial seed is always the same.  This
+is convenient when you are debugging a program, but it is unhelpful if
+you want the program to behave unpredictably.  If you want a different
+pseudo-random series each time your program runs, you must specify a
+different seed each time.  For ordinary purposes, basing the seed on the
+current time works well.  For random numbers in cryptography,
+@pxref{Unpredictable Bytes}.
+
+You can obtain repeatable sequences of numbers on a particular machine type
+by specifying the same initial seed value for the random number
+generator.  There is no standard meaning for a particular seed value;
+the same seed, used in different C libraries or on different CPU types,
+will give you different random numbers.
+
+@Theglibc{} supports the standard @w{ISO C} random number functions
+plus two other sets derived from BSD and SVID.  The BSD and @w{ISO C}
+functions provide identical, somewhat limited functionality.  If only a
+small number of random bits are required, we recommend you use the
+@w{ISO C} interface, @code{rand} and @code{srand}.  The SVID functions
+provide a more flexible interface, which allows better random number
+generator algorithms, provides more random bits (up to 48) per call, and
+can provide random floating-point numbers.  These functions are required
+by the XPG standard and therefore will be present in all modern Unix
+systems.
+
+@menu
+* ISO Random::                  @code{rand} and friends.
+* BSD Random::                  @code{random} and friends.
+* SVID Random::                 @code{drand48} and friends.
+@end menu
+
+@node ISO Random
+@subsection ISO C Random Number Functions
+
+This section describes the random number functions that are part of
+the @w{ISO C} standard.
+
+To use these facilities, you should include the header file
+@file{stdlib.h} in your program.
+@pindex stdlib.h
+
+@deftypevr Macro int RAND_MAX
+@standards{ISO, stdlib.h}
+The value of this macro is an integer constant representing the largest
+value the @code{rand} function can return.  In @theglibc{}, it is
+@code{2147483647}, which is the largest signed integer representable in
+32 bits.  In other libraries, it may be as low as @code{32767}.
+@end deftypevr
+
+@deftypefun int rand (void)
+@standards{ISO, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+@c Just calls random.
+The @code{rand} function returns the next pseudo-random number in the
+series.  The value ranges from @code{0} to @code{RAND_MAX}.
+@end deftypefun
+
+@deftypefun void srand (unsigned int @var{seed})
+@standards{ISO, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+@c Alias to srandom.
+This function establishes @var{seed} as the seed for a new series of
+pseudo-random numbers.  If you call @code{rand} before a seed has been
+established with @code{srand}, it uses the value @code{1} as a default
+seed.
+
+To produce a different pseudo-random series each time your program is
+run, do @code{srand (time (0))}.
+@end deftypefun
+
+POSIX.1 extended the C standard functions to support reproducible random
+numbers in multi-threaded programs.  However, the extension is badly
+designed and unsuitable for serious work.
+
+@deftypefun int rand_r (unsigned int *@var{seed})
+@standards{POSIX.1, stdlib.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+This function returns a random number in the range 0 to @code{RAND_MAX}
+just as @code{rand} does.  However, all its state is stored in the
+@var{seed} argument.  This means the RNG's state can only have as many
+bits as the type @code{unsigned int} has.  This is far too few to
+provide a good RNG.
+
+If your program requires a reentrant RNG, we recommend you use the
+reentrant GNU extensions to the SVID random number generator.  The
+POSIX.1 interface should only be used when the GNU extensions are not
+available.
+@end deftypefun
+
+
+@node BSD Random
+@subsection BSD Random Number Functions
+
+This section describes a set of random number generation functions that
+are derived from BSD.  There is no advantage to using these functions
+with @theglibc{}; we support them for BSD compatibility only.
+
+The prototypes for these functions are in @file{stdlib.h}.
+@pindex stdlib.h
+
+@deftypefun {long int} random (void)
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+@c Takes a lock and calls random_r with an automatic variable and the
+@c global state, while holding a lock.
+This function returns the next pseudo-random number in the sequence.
+The value returned ranges from @code{0} to @code{2147483647}.
+
+@strong{NB:} Temporarily this function was defined to return a
+@code{int32_t} value to indicate that the return value always contains
+32 bits even if @code{long int} is wider.  The standard demands it
+differently.  Users must always be aware of the 32-bit limitation,
+though.
+@end deftypefun
+
+@deftypefun void srandom (unsigned int @var{seed})
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+@c Takes a lock and calls srandom_r with an automatic variable and a
+@c static buffer.  There's no MT-safety issue because the static buffer
+@c is internally protected by a lock, although other threads may modify
+@c the set state before it is used.
+The @code{srandom} function sets the state of the random number
+generator based on the integer @var{seed}.  If you supply a @var{seed} value
+of @code{1}, this will cause @code{random} to reproduce the default set
+of random numbers.
+
+To produce a different set of pseudo-random numbers each time your
+program runs, do @code{srandom (time (0))}.
+@end deftypefun
+
+@deftypefun {char *} initstate (unsigned int @var{seed}, char *@var{state}, size_t @var{size})
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+The @code{initstate} function is used to initialize the random number
+generator state.  The argument @var{state} is an array of @var{size}
+bytes, used to hold the state information.  It is initialized based on
+@var{seed}.  The size must be between 8 and 256 bytes, and should be a
+power of two.  The bigger the @var{state} array, the better.
+
+The return value is the previous value of the state information array.
+You can use this value later as an argument to @code{setstate} to
+restore that state.
+@end deftypefun
+
+@deftypefun {char *} setstate (char *@var{state})
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+The @code{setstate} function restores the random number state
+information @var{state}.  The argument must have been the result of
+a previous call to @var{initstate} or @var{setstate}.
+
+The return value is the previous value of the state information array.
+You can use this value later as an argument to @code{setstate} to
+restore that state.
+
+If the function fails the return value is @code{NULL}.
+@end deftypefun
+
+The four functions described so far in this section all work on a state
+which is shared by all threads.  The state is not directly accessible to
+the user and can only be modified by these functions.  This makes it
+hard to deal with situations where each thread should have its own
+pseudo-random number generator.
+
+@Theglibc{} contains four additional functions which contain the
+state as an explicit parameter and therefore make it possible to handle
+thread-local PRNGs.  Besides this there is no difference.  In fact, the
+four functions already discussed are implemented internally using the
+following interfaces.
+
+The @file{stdlib.h} header contains a definition of the following type:
+
+@deftp {Data Type} {struct random_data}
+@standards{GNU, stdlib.h}
+
+Objects of type @code{struct random_data} contain the information
+necessary to represent the state of the PRNG.  Although a complete
+definition of the type is present the type should be treated as opaque.
+@end deftp
+
+The functions modifying the state follow exactly the already described
+functions.
+
+@deftypefun int random_r (struct random_data *restrict @var{buf}, int32_t *restrict @var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{random_r} function behaves exactly like the @code{random}
+function except that it uses and modifies the state in the object
+pointed to by the first parameter instead of the global state.
+@end deftypefun
+
+@deftypefun int srandom_r (unsigned int @var{seed}, struct random_data *@var{buf})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{srandom_r} function behaves exactly like the @code{srandom}
+function except that it uses and modifies the state in the object
+pointed to by the second parameter instead of the global state.
+@end deftypefun
+
+@deftypefun int initstate_r (unsigned int @var{seed}, char *restrict @var{statebuf}, size_t @var{statelen}, struct random_data *restrict @var{buf})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{initstate_r} function behaves exactly like the @code{initstate}
+function except that it uses and modifies the state in the object
+pointed to by the fourth parameter instead of the global state.
+@end deftypefun
+
+@deftypefun int setstate_r (char *restrict @var{statebuf}, struct random_data *restrict @var{buf})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buf}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{setstate_r} function behaves exactly like the @code{setstate}
+function except that it uses and modifies the state in the object
+pointed to by the first parameter instead of the global state.
+@end deftypefun
+
+@node SVID Random
+@subsection SVID Random Number Function
+
+The C library on SVID systems contains yet another kind of random number
+generator functions.  They use a state of 48 bits of data.  The user can
+choose among a collection of functions which return the random bits
+in different forms.
+
+Generally there are two kinds of function.  The first uses a state of
+the random number generator which is shared among several functions and
+by all threads of the process.  The second requires the user to handle
+the state.
+
+All functions have in common that they use the same congruential
+formula with the same constants.  The formula is
+
+@smallexample
+Y = (a * X + c) mod m
+@end smallexample
+
+@noindent
+where @var{X} is the state of the generator at the beginning and
+@var{Y} the state at the end.  @code{a} and @code{c} are constants
+determining the way the generator works.  By default they are
+
+@smallexample
+a = 0x5DEECE66D = 25214903917
+c = 0xb = 11
+@end smallexample
+
+@noindent
+but they can also be changed by the user.  @code{m} is of course 2^48
+since the state consists of a 48-bit array.
+
+The prototypes for these functions are in @file{stdlib.h}.
+@pindex stdlib.h
+
+
+@deftypefun double drand48 (void)
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+@c Uses of the static state buffer are not guarded by a lock (thus
+@c @mtasurace:drand48), so they may be found or left at a
+@c partially-updated state in case of calls from within signal handlers
+@c or cancellation.  None of this will break safety rules or invoke
+@c undefined behavior, but it may affect randomness.
+This function returns a @code{double} value in the range of @code{0.0}
+to @code{1.0} (exclusive).  The random bits are determined by the global
+state of the random number generator in the C library.
+
+Since the @code{double} type according to @w{IEEE 754} has a 52-bit
+mantissa this means 4 bits are not initialized by the random number
+generator.  These are (of course) chosen to be the least significant
+bits and they are initialized to @code{0}.
+@end deftypefun
+
+@deftypefun double erand48 (unsigned short int @var{xsubi}[3])
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+@c The static buffer is just initialized with default parameters, which
+@c are later read to advance the state held in xsubi.
+This function returns a @code{double} value in the range of @code{0.0}
+to @code{1.0} (exclusive), similarly to @code{drand48}.  The argument is
+an array describing the state of the random number generator.
+
+This function can be called subsequently since it updates the array to
+guarantee random numbers.  The array should have been initialized before
+initial use to obtain reproducible results.
+@end deftypefun
+
+@deftypefun {long int} lrand48 (void)
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+The @code{lrand48} function returns an integer value in the range of
+@code{0} to @code{2^31} (exclusive).  Even if the size of the @code{long
+int} type can take more than 32 bits, no higher numbers are returned.
+The random bits are determined by the global state of the random number
+generator in the C library.
+@end deftypefun
+
+@deftypefun {long int} nrand48 (unsigned short int @var{xsubi}[3])
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+This function is similar to the @code{lrand48} function in that it
+returns a number in the range of @code{0} to @code{2^31} (exclusive) but
+the state of the random number generator used to produce the random bits
+is determined by the array provided as the parameter to the function.
+
+The numbers in the array are updated afterwards so that subsequent calls
+to this function yield different results (as is expected of a random
+number generator).  The array should have been initialized before the
+first call to obtain reproducible results.
+@end deftypefun
+
+@deftypefun {long int} mrand48 (void)
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+The @code{mrand48} function is similar to @code{lrand48}.  The only
+difference is that the numbers returned are in the range @code{-2^31} to
+@code{2^31} (exclusive).
+@end deftypefun
+
+@deftypefun {long int} jrand48 (unsigned short int @var{xsubi}[3])
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+The @code{jrand48} function is similar to @code{nrand48}.  The only
+difference is that the numbers returned are in the range @code{-2^31} to
+@code{2^31} (exclusive).  For the @code{xsubi} parameter the same
+requirements are necessary.
+@end deftypefun
+
+The internal state of the random number generator can be initialized in
+several ways.  The methods differ in the completeness of the
+information provided.
+
+@deftypefun void srand48 (long int @var{seedval})
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+The @code{srand48} function sets the most significant 32 bits of the
+internal state of the random number generator to the least
+significant 32 bits of the @var{seedval} parameter.  The lower 16 bits
+are initialized to the value @code{0x330E}.  Even if the @code{long
+int} type contains more than 32 bits only the lower 32 bits are used.
+
+Owing to this limitation, initialization of the state of this
+function is not very useful.  But it makes it easy to use a construct
+like @code{srand48 (time (0))}.
+
+A side-effect of this function is that the values @code{a} and @code{c}
+from the internal state, which are used in the congruential formula,
+are reset to the default values given above.  This is of importance once
+the user has called the @code{lcong48} function (see below).
+@end deftypefun
+
+@deftypefun {unsigned short int *} seed48 (unsigned short int @var{seed16v}[3])
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+The @code{seed48} function initializes all 48 bits of the state of the
+internal random number generator from the contents of the parameter
+@var{seed16v}.  Here the lower 16 bits of the first element of
+@var{seed16v} initialize the least significant 16 bits of the internal
+state, the lower 16 bits of @code{@var{seed16v}[1]} initialize the mid-order
+16 bits of the state and the 16 lower bits of @code{@var{seed16v}[2]}
+initialize the most significant 16 bits of the state.
+
+Unlike @code{srand48} this function lets the user initialize all 48 bits
+of the state.
+
+The value returned by @code{seed48} is a pointer to an array containing
+the values of the internal state before the change.  This might be
+useful to restart the random number generator at a certain state.
+Otherwise the value can simply be ignored.
+
+As for @code{srand48}, the values @code{a} and @code{c} from the
+congruential formula are reset to the default values.
+@end deftypefun
+
+There is one more function to initialize the random number generator
+which enables you to specify even more information by allowing you to
+change the parameters in the congruential formula.
+
+@deftypefun void lcong48 (unsigned short int @var{param}[7])
+@standards{SVID, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:drand48}}@asunsafe{}@acunsafe{@acucorrupt{}}}
+The @code{lcong48} function allows the user to change the complete state
+of the random number generator.  Unlike @code{srand48} and
+@code{seed48}, this function also changes the constants in the
+congruential formula.
+
+From the seven elements in the array @var{param} the least significant
+16 bits of the entries @code{@var{param}[0]} to @code{@var{param}[2]}
+determine the initial state, the least significant 16 bits of
+@code{@var{param}[3]} to @code{@var{param}[5]} determine the 48 bit
+constant @code{a} and @code{@var{param}[6]} determines the 16-bit value
+@code{c}.
+@end deftypefun
+
+All the above functions have in common that they use the global
+parameters for the congruential formula.  In multi-threaded programs it
+might sometimes be useful to have different parameters in different
+threads.  For this reason all the above functions have a counterpart
+which works on a description of the random number generator in the
+user-supplied buffer instead of the global state.
+
+Please note that it is no problem if several threads use the global
+state if all threads use the functions which take a pointer to an array
+containing the state.  The random numbers are computed following the
+same loop but if the state in the array is different all threads will
+obtain an individual random number generator.
+
+The user-supplied buffer must be of type @code{struct drand48_data}.
+This type should be regarded as opaque and not manipulated directly.
+
+@deftypefun int drand48_r (struct drand48_data *@var{buffer}, double *@var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+This function is equivalent to the @code{drand48} function with the
+difference that it does not modify the global random number generator
+parameters but instead the parameters in the buffer supplied through the
+pointer @var{buffer}.  The random number is returned in the variable
+pointed to by @var{result}.
+
+The return value of the function indicates whether the call succeeded.
+If the value is less than @code{0} an error occurred and @var{errno} is
+set to indicate the problem.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int erand48_r (unsigned short int @var{xsubi}[3], struct drand48_data *@var{buffer}, double *@var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{erand48_r} function works like @code{erand48}, but in addition
+it takes an argument @var{buffer} which describes the random number
+generator.  The state of the random number generator is taken from the
+@code{xsubi} array, the parameters for the congruential formula from the
+global random number generator data.  The random number is returned in
+the variable pointed to by @var{result}.
+
+The return value is non-negative if the call succeeded.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int lrand48_r (struct drand48_data *@var{buffer}, long int *@var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+This function is similar to @code{lrand48}, but in addition it takes a
+pointer to a buffer describing the state of the random number generator
+just like @code{drand48}.
+
+If the return value of the function is non-negative the variable pointed
+to by @var{result} contains the result.  Otherwise an error occurred.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int nrand48_r (unsigned short int @var{xsubi}[3], struct drand48_data *@var{buffer}, long int *@var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{nrand48_r} function works like @code{nrand48} in that it
+produces a random number in the range @code{0} to @code{2^31}.  But instead
+of using the global parameters for the congruential formula it uses the
+information from the buffer pointed to by @var{buffer}.  The state is
+described by the values in @var{xsubi}.
+
+If the return value is non-negative the variable pointed to by
+@var{result} contains the result.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int mrand48_r (struct drand48_data *@var{buffer}, long int *@var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+This function is similar to @code{mrand48} but like the other reentrant
+functions it uses the random number generator described by the value in
+the buffer pointed to by @var{buffer}.
+
+If the return value is non-negative the variable pointed to by
+@var{result} contains the result.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int jrand48_r (unsigned short int @var{xsubi}[3], struct drand48_data *@var{buffer}, long int *@var{result})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+The @code{jrand48_r} function is similar to @code{jrand48}.  Like the
+other reentrant functions of this function family it uses the
+congruential formula parameters from the buffer pointed to by
+@var{buffer}.
+
+If the return value is non-negative the variable pointed to by
+@var{result} contains the result.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+Before any of the above functions are used the buffer of type
+@code{struct drand48_data} should be initialized.  The easiest way to do
+this is to fill the whole buffer with null bytes, e.g. by
+
+@smallexample
+memset (buffer, '\0', sizeof (struct drand48_data));
+@end smallexample
+
+@noindent
+Using any of the reentrant functions of this family now will
+automatically initialize the random number generator to the default
+values for the state and the parameters of the congruential formula.
+
+The other possibility is to use any of the functions which explicitly
+initialize the buffer.  Though it might be obvious how to initialize the
+buffer from looking at the parameter to the function, it is highly
+recommended to use these functions since the result might not always be
+what you expect.
+
+@deftypefun int srand48_r (long int @var{seedval}, struct drand48_data *@var{buffer})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+The description of the random number generator represented by the
+information in @var{buffer} is initialized similarly to what the function
+@code{srand48} does.  The state is initialized from the parameter
+@var{seedval} and the parameters for the congruential formula are
+initialized to their default values.
+
+If the return value is non-negative the function call succeeded.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int seed48_r (unsigned short int @var{seed16v}[3], struct drand48_data *@var{buffer})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+This function is similar to @code{srand48_r} but like @code{seed48} it
+initializes all 48 bits of the state from the parameter @var{seed16v}.
+
+If the return value is non-negative the function call succeeded.  It
+does not return a pointer to the previous state of the random number
+generator like the @code{seed48} function does.  If the user wants to
+preserve the state for a later re-run s/he can copy the whole buffer
+pointed to by @var{buffer}.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@deftypefun int lcong48_r (unsigned short int @var{param}[7], struct drand48_data *@var{buffer})
+@standards{GNU, stdlib.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:buffer}}@assafe{}@acunsafe{@acucorrupt{}}}
+This function initializes all aspects of the random number generator
+described in @var{buffer} with the data in @var{param}.  Here it is
+especially true that the function does more than just copying the
+contents of @var{param} and @var{buffer}.  More work is required and
+therefore it is important to use this function rather than initializing
+the random number generator directly.
+
+If the return value is non-negative the function call succeeded.
+
+This function is a GNU extension and should not be used in portable
+programs.
+@end deftypefun
+
+@node Unpredictable Bytes
+@section Generating Unpredictable Bytes
+
+Some cryptographic applications (such as session key generation) need
+unpredictable bytes.
+
+In general, application code should use a deterministic random bit
+generator, which could call the @code{getentropy} function described
+below internally to obtain randomness to seed the generator.  The
+@code{getrandom} function is intended for low-level applications which
+need additional control over the blocking behavior.
+
+@deftypefun int getentropy (void *@var{buffer}, size_t @var{length})
+@standards{GNU, sys/random.h}
+@safety{@mtsafe{}@assafe{}@acsafe{}}
+
+This function writes @var{length} bytes of random data to the array
+starting at @var{buffer}, which must be at most 256 bytes long.  The
+function returns zero on success.  On failure, it returns @code{-1} and
+@code{errno} is updated accordingly.
+
+The @code{getentropy} function is declared in the header file
+@file{sys/random.h}.  It is derived from OpenBSD.
+
+The @code{getentropy} function is not a cancellation point.  A call to
+@code{getentropy} can block if the system has just booted and the kernel
+entropy pool has not yet been initialized.  In this case, the function
+will keep blocking even if a signal arrives, and return only after the
+entropy pool has been initialized.
+
+The @code{getentropy} function can fail with several errors, some of
+which are listed below.
+
+@table @code
+@item ENOSYS
+The kernel does not implement the required system call.
+
+@item EFAULT
+The combination of @var{buffer} and @var{length} arguments specifies
+an invalid memory range.
+
+@item EIO
+More than 256 bytes of randomness have been requested, or the buffer
+could not be overwritten with random data for an unspecified reason.
+
+@end table
+
+@end deftypefun
+
+@deftypefun ssize_t getrandom (void *@var{buffer}, size_t @var{length}, unsigned int @var{flags})
+@standards{GNU, sys/random.h}
+@safety{@mtsafe{}@assafe{}@acsafe{}}
+
+This function writes @var{length} bytes of random data to the array
+starting at @var{buffer}.  On success, this function returns the number
+of bytes which have been written to the buffer (which can be less than
+@var{length}).  On error, @code{-1} is returned, and @code{errno} is
+updated accordingly.
+
+The @code{getrandom} function is declared in the header file
+@file{sys/random.h}.  It is a GNU extension.
+
+The following flags are defined for the @var{flags} argument:
+
+@table @code
+@item GRND_RANDOM
+Use the @file{/dev/random} (blocking) pool instead of the
+@file{/dev/urandom} (non-blocking) pool to obtain randomness.  If the
+@code{GRND_RANDOM} flag is specified, the @code{getrandom} function can
+block even after the randomness source has been initialized.
+
+@item GRND_NONBLOCK
+Instead of blocking, return to the caller immediately if no data is
+available.
+@end table
+
+The @code{getrandom} function is a cancellation point.
+
+Obtaining randomness from the @file{/dev/urandom} pool (i.e., a call
+without the @code{GRND_RANDOM} flag) can block if the system has just
+booted and the pool has not yet been initialized.
+
+The @code{getrandom} function can fail with several errors, some of
+which are listed below.  In addition, the function may not fill the
+buffer completely and return a value less than @var{length}.
+
+@table @code
+@item ENOSYS
+The kernel does not implement the @code{getrandom} system call.
+
+@item EAGAIN
+No random data was available and @code{GRND_NONBLOCK} was specified in
+@var{flags}.
+
+@item EFAULT
+The combination of @var{buffer} and @var{length} arguments specifies
+an invalid memory range.
+
+@item EINTR
+The system call was interrupted.  During the system boot process, before
+the kernel randomness pool is initialized, this can happen even if
+@var{flags} is zero.
+
+@item EINVAL
+The @var{flags} argument contains an invalid combination of flags.
+@end table
+
+@end deftypefun
diff --git a/manual/terminal.texi b/manual/terminal.texi
index 4aace48b14..0b275fc002 100644
--- a/manual/terminal.texi
+++ b/manual/terminal.texi
@@ -24,6 +24,7 @@ descriptor is and how to open a file descriptor for a terminal device.
 * Line Control::                Sending break sequences, clearing
                                  terminal buffers @dots{}
 * Noncanon Example::            How to read single characters without echo.
+* getpass::                     Prompting the user for a password.
 * Pseudo-Terminals::            How to open a pseudo-terminal.
 @end menu
 
@@ -1871,6 +1872,50 @@ existing shells do not actually do this, so you may wish to establish
 handlers for job control signals that reset terminal modes.  The above
 example does so.
 
+@node getpass
+@section Reading Passwords
+
+When reading in a password, it is desirable to avoid displaying it on
+the screen, to help keep it secret.  The following function handles this
+in a convenient way.
+
+@deftypefun {char *} getpass (const char *@var{prompt})
+@standards{BSD, unistd.h}
+@safety{@prelim{}@mtunsafe{@mtasuterm{}}@asunsafe{@ascuheap{} @asulock{} @asucorrupt{}}@acunsafe{@acuterm{} @aculock{} @acucorrupt{}}}
+@c This function will attempt to create a stream for terminal I/O, but
+@c will fallback to stdio/stderr.  It attempts to change the terminal
+@c mode in a thread-unsafe way, write out the prompt, read the password,
+@c then restore the terminal mode.  It has a cleanup to close the stream
+@c in case of (synchronous) cancellation, but not to restore the
+@c terminal mode.
+
+@code{getpass} outputs @var{prompt}, then reads a string in from the
+terminal without echoing it.  It tries to connect to the real terminal,
+@file{/dev/tty}, if possible, to encourage users not to put plaintext
+passwords in files; otherwise, it uses @code{stdin} and @code{stderr}.
+@code{getpass} also disables the INTR, QUIT, and SUSP characters on the
+terminal using the @code{ISIG} terminal attribute (@pxref{Local Modes}).
+The terminal is flushed before and after @code{getpass}, so that
+characters of a mistyped password are not accidentally visible.
+
+In other C libraries, @code{getpass} may only return the first
+@code{PASS_MAX} bytes of a password.  @Theglibc{} has no limit, so
+@code{PASS_MAX} is undefined.
+
+The prototype for this function is in @file{unistd.h}.  @code{PASS_MAX}
+would be defined in @file{limits.h}.
+@end deftypefun
+
+This precise set of operations may not suit all possible situations.  In
+this case, it is recommended that users write their own @code{getpass}
+substitute.  For instance, a very simple substitute is as follows:
+
+@smallexample
+@include mygetpass.c.texi
+@end smallexample
+
+The substitute takes the same parameters as @code{getline}
+(@pxref{Line Input}); the user must print any prompt desired.
 
 @node Pseudo-Terminals
 @section Pseudo-Terminals
diff --git a/manual/time.texi b/manual/time.texi
index 4d154452eb..d0821703c0 100644
--- a/manual/time.texi
+++ b/manual/time.texi
@@ -1,4 +1,4 @@
-@node Date and Time, Resource Usage And Limitation, Arithmetic, Top
+@node Date and Time, Resource Usage And Limitation, Random Number Generation, Top
 @c %MENU% Functions for getting the date and time and formatting them nicely
 @chapter Date and Time
 
-- 
2.17.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 4/4] New configure option --disable-crypt.
  2018-05-06 17:52 [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Zack Weinberg
  2018-05-06 17:51 ` [PATCH 3/4] Deprecate DES encryption functions Zack Weinberg
  2018-05-06 17:52 ` [PATCH 2/4] Revise manual sections on cryptography and random numbers Zack Weinberg
@ 2018-05-06 17:52 ` Zack Weinberg
  2018-05-08 15:00   ` Florian Weimer
  2018-05-06 17:52 ` [PATCH 1/4] Reorganize manual sections on cryptography and random numbers Zack Weinberg
  2018-05-08 22:56 ` [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Rical Jasan
  4 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2018-05-06 17:52 UTC (permalink / raw)
  To: libc-alpha; +Cc: carlos, fweimer, rj

Some Linux distributions are experimenting with a new, separately
maintained and hopefully more agile implementation of the crypt(3)
APIs.  To facilitate this, add a configure option which disables
glibc's embedded libcrypt.  When this option is given, libcrypt.*
and crypt.h will not be built nor installed.

unistd.h continues to define _XOPEN_CRYPT to 1 and to declare crypt.

The bulk of the patch is just various places that need to take note of
libcrypt possibly not getting built.

        * configure.ac: New command-line option --disable-crypt.
        Force --disable-nss-crypt when --disable-crypt is given, with a
        warning if it was explicitly enabled.
        * configure: Regenerate.
        * config.make.in: New boolean substitution variable $(build-crypt).
        * Makeconfig: Only include 'crypt' in all-subdirs and rpath-dirs
        when $(build-crypt).
        * manual/install.texi: Document --disable-crypt.
        * INSTALL: Regenerate.

        * crypt/Makefile: Remove code conditional on $(crypt-in-libc),
        which is never set.
        * conform/Makefile: Only include libcrypt.a in
        linknamespace-libs-xsi and linknamespace-libs-XPG4
        when $(build-crypt).
        * elf/Makefile (CFLAGS-tst-linkall-static.c): Only define
        USE_CRYPT to 1 when $(build-crypt).
        (tst-linkall-static): Only link libcrypt.a when $(build-crypt).
        (localplt-built-dso): Only add libcrypt.so when $(build-crypt).
        * elf/tst-linkall-static.c: Only include crypt.h when USE_CRYPT.

        * crypt/crypt.h: Update comments above crypt.
        * posix/unistd.h: Update comments above crypt.
---
 INSTALL                  | 11 +++++++++++
 Makeconfig               |  9 +++++++--
 NEWS                     | 12 ++++++++++++
 config.make.in           |  1 +
 configure                | 18 ++++++++++++++++++
 configure.ac             | 11 +++++++++++
 conform/Makefile         | 11 +++++++----
 crypt/Makefile           |  4 ----
 crypt/crypt.h            |  5 ++++-
 elf/Makefile             | 27 +++++++++++++++++++--------
 elf/tst-linkall-static.c |  4 +++-
 manual/install.texi      | 12 ++++++++++++
 posix/unistd.h           |  7 ++++---
 13 files changed, 109 insertions(+), 23 deletions(-)

diff --git a/INSTALL b/INSTALL
index 052b1b6f89..6de609c9d6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -197,6 +197,17 @@ if 'CFLAGS' is specified it must enable optimization.  For example:
      libnss_nisplus are not built at all.  Use this option to enable
      libnsl with all depending NSS modules and header files.
 
+'--disable-crypt'
+     Do not install the password-hashing library 'libcrypt' or the
+     header file 'crypt.h'.  'unistd.h' will still declare the function
+     'crypt', as required by POSIX. Using this option does not change
+     the set of programs that may need to be linked with '-lcrypt'; it
+     only means that the GNU C Library will not provide that library.
+
+     This option is for hackers and distributions experimenting with
+     independently-maintained implementations of libcrypt.  It may
+     become the default in a future release.
+
 '--disable-experimental-malloc'
      By default, a per-thread cache is enabled in 'malloc'.  While this
      cache can be disabled on a per-application basis using tunables
diff --git a/Makeconfig b/Makeconfig
index 1afe86475c..608ffe648c 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -566,7 +566,7 @@ link-libc-printers-tests = $(link-libc-rpath) \
 			   $(link-libc-tests-after-rpath-link)
 
 # This is how to find at build-time things that will be installed there.
-rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec support
+rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support
 rpath-link = \
 $(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
 else  # build-static
@@ -1205,9 +1205,14 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal	    \
 	      stdlib stdio-common libio malloc string wcsmbs time dirent    \
 	      grp pwd posix io termios resource misc socket sysvipc gmon    \
 	      gnulib iconv iconvdata wctype manual shadow gshadow po argp   \
-	      crypt localedata timezone rt conform debug mathvec support    \
+	      localedata timezone rt conform debug mathvec support	    \
 	      dlfcn elf
 
+ifeq ($(build-crypt),yes)
+all-subdirs += crypt
+rpath-dirs += crypt
+endif
+
 ifndef avoid-generated
 # sysd-sorted itself will contain rules making the sysd-sorted target
 # depend on Depend files.  But if you just added a Depend file to an
diff --git a/NEWS b/NEWS
index 2fe2da8b59..cfc58f71bb 100644
--- a/NEWS
+++ b/NEWS
@@ -71,6 +71,18 @@ Deprecated and removed features, and other changes affecting compatibility:
   encrypt and setkey are not thread-safe.  Software that still uses these
   functions should switch to a modern cryptography library, such as GnuTLS.
 
+* We have tentative plans to deprecate glibc's implementation of the
+  password-hashing functions 'crypt' and 'crypt_r'.  We will continue
+  to declare crypt in <unistd.h>, as required by POSIX, and programs
+  that use crypt or crypt_r should not need to change at all.  However,
+  the header file <crypt.h> and library libcrypt.{a,so} will come from
+  a separate development project that will, we hope, keep up better with
+  new password-hashing algorithms.
+
+  In this release, if the configure option --disable-crypt is used,
+  glibc will not install <crypt.h> or libcrypt.  The plan is to make
+  this the default behavior in a future release.
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/config.make.in b/config.make.in
index 9e5e24b2c6..d9891b2cd8 100644
--- a/config.make.in
+++ b/config.make.in
@@ -96,6 +96,7 @@ cross-compiling = @cross_compiling@
 force-install = @force_install@
 link-obsolete-rpc = @link_obsolete_rpc@
 build-obsolete-nsl = @build_obsolete_nsl@
+build-crypt = @build_crypt@
 build-nscd = @build_nscd@
 use-nscd = @use_nscd@
 build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
diff --git a/configure b/configure
index 7a8bd3f817..7317c1aee4 100755
--- a/configure
+++ b/configure
@@ -676,6 +676,7 @@ build_obsolete_nsl
 link_obsolete_rpc
 libc_cv_static_nss_crypt
 libc_cv_nss_crypt
+build_crypt
 experimental_malloc
 enable_werror
 all_warnings
@@ -779,6 +780,7 @@ enable_all_warnings
 enable_werror
 enable_multi_arch
 enable_experimental_malloc
+enable_crypt
 enable_nss_crypt
 enable_obsolete_rpc
 enable_obsolete_nsl
@@ -1448,6 +1450,8 @@ Optional Features:
                           architectures
   --disable-experimental-malloc
                           disable experimental malloc features
+  --disable-crypt         do not build nor install the password hashing
+                          library, libcrypt
   --enable-nss-crypt      enable libcrypt to use nss
   --enable-obsolete-rpc   build and install the obsolete RPC code for
                           link-time usage
@@ -3505,6 +3509,15 @@ fi
 
 
 
+# Check whether --enable-crypt was given.
+if test "${enable_crypt+set}" = set; then :
+  enableval=$enable_crypt; build_crypt=$enableval
+else
+  build_crypt=yes
+fi
+
+
+
 # Check whether --enable-nss-crypt was given.
 if test "${enable_nss_crypt+set}" = set; then :
   enableval=$enable_nss_crypt; nss_crypt=$enableval
@@ -3512,6 +3525,11 @@ else
   nss_crypt=no
 fi
 
+if test x$build_libcrypt = xno && test x$nss_crypt = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-nss-crypt has no effect when libcrypt is disabled" >&5
+$as_echo "$as_me: WARNING: --enable-nss-crypt has no effect when libcrypt is disabled" >&2;}
+  nss_crypt=no
+fi
 if test x$nss_crypt = xyes; then
   nss_includes=-I$(nss-config --includedir 2>/dev/null)
   if test $? -ne 0; then
diff --git a/configure.ac b/configure.ac
index ca1282a6b3..05e03f2f72 100644
--- a/configure.ac
+++ b/configure.ac
@@ -302,11 +302,22 @@ AC_ARG_ENABLE([experimental-malloc],
 	      [experimental_malloc=yes])
 AC_SUBST(experimental_malloc)
 
+AC_ARG_ENABLE([crypt],
+              AC_HELP_STRING([--disable-crypt],
+                             [do not build nor install the password hashing library, libcrypt]),
+              [build_crypt=$enableval],
+              [build_crypt=yes])
+AC_SUBST(build_crypt)
+
 AC_ARG_ENABLE([nss-crypt],
 	      AC_HELP_STRING([--enable-nss-crypt],
 			     [enable libcrypt to use nss]),
 	      [nss_crypt=$enableval],
 	      [nss_crypt=no])
+if test x$build_libcrypt = xno && test x$nss_crypt = xyes; then
+  AC_MSG_WARN([--enable-nss-crypt has no effect when libcrypt is disabled])
+  nss_crypt=no
+fi
 if test x$nss_crypt = xyes; then
   nss_includes=-I$(nss-config --includedir 2>/dev/null)
   if test $? -ne 0; then
diff --git a/conform/Makefile b/conform/Makefile
index 864fdeca21..74fbda0786 100644
--- a/conform/Makefile
+++ b/conform/Makefile
@@ -193,13 +193,11 @@ linknamespace-libs-thr = $(linknamespace-libs-isoc) \
 			 $(common-objpfx)rt/librt.a $(static-thread-library)
 linknamespace-libs-posix = $(linknamespace-libs-thr) \
 			   $(common-objpfx)dlfcn/libdl.a
-linknamespace-libs-xsi = $(linknamespace-libs-posix) \
-			 $(common-objpfx)crypt/libcrypt.a
+linknamespace-libs-xsi = $(linknamespace-libs-posix)
 linknamespace-libs-ISO = $(linknamespace-libs-isoc)
 linknamespace-libs-ISO99 = $(linknamespace-libs-isoc)
 linknamespace-libs-ISO11 = $(linknamespace-libs-isoc)
-linknamespace-libs-XPG4 = $(linknamespace-libs-isoc) \
-			  $(common-objpfx)crypt/libcrypt.a
+linknamespace-libs-XPG4 = $(linknamespace-libs-isoc)
 linknamespace-libs-XPG42 = $(linknamespace-libs-XPG4)
 linknamespace-libs-POSIX = $(linknamespace-libs-thr)
 linknamespace-libs-UNIX98 = $(linknamespace-libs-xsi)
@@ -209,6 +207,11 @@ linknamespace-libs-XOPEN2K8 = $(linknamespace-libs-xsi)
 linknamespace-libs = $(foreach std,$(conformtest-standards),\
 				   $(linknamespace-libs-$(std)))
 
+ifeq ($(build-crypt),yes)
+linknamespace-libs-xsi += $(common-objpfx)crypt/libcrypt.a
+linknamespace-libs-XPG4 += $(common-objpfx)crypt/libcrypt.a
+endif
+
 $(linknamespace-symlist-stdlibs-tests): $(objpfx)symlist-stdlibs-%: \
 					$(linknamespace-libs)
 	LC_ALL=C $(READELF) -W -s $(linknamespace-libs-$*) > $@; \
diff --git a/crypt/Makefile b/crypt/Makefile
index e122bcebf0..1e2f21bf52 100644
--- a/crypt/Makefile
+++ b/crypt/Makefile
@@ -35,10 +35,6 @@ tests := cert md5c-test sha256c-test sha512c-test badsalttest
 # cert.c tests the deprecated setkey/encrypt interface
 CFLAGS-cert.c = -Wno-deprecated-declarations
 
-ifeq ($(crypt-in-libc),yes)
-routines += $(libcrypt-routines)
-endif
-
 ifeq ($(nss-crypt),yes)
 nss-cpp-flags := -DUSE_NSS \
   -I$(shell nss-config --includedir) -I$(shell nspr-config --includedir)
diff --git a/crypt/crypt.h b/crypt/crypt.h
index 22cf13ff89..4f928901f3 100644
--- a/crypt/crypt.h
+++ b/crypt/crypt.h
@@ -28,7 +28,10 @@
 
 __BEGIN_DECLS
 
-/* Encrypt at most 8 characters from KEY using salt to perturb DES.  */
+/* Hash a password, KEY, for storage in /etc/shadow.  SALT selects the
+   hashing algorithm to be used, and ensures that no two users' passwords
+   are hashed to the same string.  The return value points to static
+   storage which will be overwritten by the next call to crypt.  */
 extern char *crypt (const char *__key, const char *__salt)
      __THROW __nonnull ((1, 2));
 
diff --git a/elf/Makefile b/elf/Makefile
index e658928305..ef9155dbd7 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -385,14 +385,21 @@ $(objpfx)tst-_dl_addr_inside_object: $(objpfx)dl-addr-obj.os
 CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag)
 endif
 
-# By default tst-linkall-static should try to use crypt routines to test
-# static libcrypt use.
+# We can only test static libcrypt use if libcrypt has been built,
+# and either NSS crypto is not in use, or static NSS libraries are
+# available.
+ifeq ($(build-crypt),no)
+CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
+else
+ifeq ($(nss-crypt),no)
+CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
+else
+ifeq ($(static-nss-crypt),no)
+CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
+else
 CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
-# However, if we are using NSS crypto and we don't have a static
-# library, then we exclude the use of crypt functions in the test.
-# We similarly exclude libcrypt.a from the static link (see below).
-ifeq (yesno,$(nss-crypt)$(static-nss-crypt))
-CFLAGS-tst-linkall-static.c += -UUSE_CRYPT -DUSE_CRYPT=0
+endif
+endif
 endif
 
 include ../Rules
@@ -1113,7 +1120,6 @@ localplt-built-dso := $(addprefix $(common-objpfx),\
 				  rt/librt.so \
 				  dlfcn/libdl.so \
 				  resolv/libresolv.so \
-				  crypt/libcrypt.so \
 		       )
 ifeq ($(build-mathvec),yes)
 localplt-built-dso += $(addprefix $(common-objpfx), mathvec/libmvec.so)
@@ -1121,6 +1127,9 @@ endif
 ifeq ($(have-thread-library),yes)
 localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library))
 endif
+ifeq ($(build-crypt),yes)
+localplt-built-dso += $(addprefix $(common-objpfx), crypt/libcrypt.so)
+endif
 
 vpath localplt.data $(+sysdep_dirs)
 
@@ -1395,6 +1404,7 @@ $(objpfx)tst-linkall-static: \
   $(common-objpfx)resolv/libanl.a \
   $(static-thread-library)
 
+ifeq ($(build-crypt),yes)
 # If we are using NSS crypto and we have the ability to link statically
 # then we include libcrypt.a, otherwise we leave out libcrypt.a and
 # link as much as we can into the tst-linkall-static test.  This assumes
@@ -1410,6 +1420,7 @@ ifeq (no,$(nss-crypt))
 $(objpfx)tst-linkall-static: \
   $(common-objpfx)crypt/libcrypt.a
 endif
+endif
 
 # The application depends on the DSO, and the DSO loads the plugin.
 # The plugin also depends on the DSO. This creates the circular
diff --git a/elf/tst-linkall-static.c b/elf/tst-linkall-static.c
index e8df38f74e..d0f2592e67 100644
--- a/elf/tst-linkall-static.c
+++ b/elf/tst-linkall-static.c
@@ -18,7 +18,9 @@
 
 #include <math.h>
 #include <pthread.h>
-#include <crypt.h>
+#if USE_CRYPT
+# include <crypt.h>
+#endif
 #include <resolv.h>
 #include <dlfcn.h>
 #include <utmp.h>
diff --git a/manual/install.texi b/manual/install.texi
index 4bbbfcffa5..ce2d049f1a 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -230,6 +230,18 @@ libnss_nisplus are not built at all.
 Use this option to enable libnsl with all depending NSS modules and
 header files.
 
+@item --disable-crypt
+Do not install the password-hashing library @file{libcrypt} or the
+header file @file{crypt.h}.  @file{unistd.h} will still declare the
+function @code{crypt}, as required by POSIX.  Using this option does
+not change the set of programs that may need to be linked with
+@option{-lcrypt}; it only means that @theglibc{} will not provide that
+library.
+
+This option is for hackers and distributions experimenting with
+independently-maintained implementations of libcrypt.  It may become
+the default in a future release.
+
 @item --disable-experimental-malloc
 By default, a per-thread cache is enabled in @code{malloc}.  While
 this cache can be disabled on a per-application basis using tunables
diff --git a/posix/unistd.h b/posix/unistd.h
index 5d4e07f6c8..fdf2d4b208 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -1119,10 +1119,11 @@ extern int fdatasync (int __fildes);
 #endif /* Use POSIX199309 */
 
 
-/* XPG4.2 specifies that prototypes for the encryption functions must
-   be defined here.  */
 #ifdef	__USE_XOPEN
-/* Encrypt at most 8 characters from KEY using salt to perturb DES.  */
+/* Hash a password, KEY, for storage in /etc/shadow.  SALT selects the
+   hashing algorithm to be used, and ensures that no two users' passwords
+   are hashed to the same string.  The return value points to static
+   storage which will be overwritten by the next call to crypt.  */
 extern char *crypt (const char *__key, const char *__salt)
      __THROW __nonnull ((1, 2));
 
-- 
2.17.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/4] Reorganize manual sections on cryptography and random numbers.
  2018-05-06 17:52 ` [PATCH 1/4] Reorganize manual sections on cryptography and random numbers Zack Weinberg
@ 2018-05-08 13:29   ` Florian Weimer
  2018-05-08 13:37     ` Zack Weinberg
  2018-05-09 11:36   ` Rical Jasan
  1 sibling, 1 reply; 19+ messages in thread
From: Florian Weimer @ 2018-05-08 13:29 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha; +Cc: carlos, rj

On 05/06/2018 07:51 PM, Zack Weinberg wrote:
> 	* manual/crypt.texi: Move most of the introductory text to the
>          'crypt' section.  Move the example programs below the
>          @deftypefun for 'crypt_r'.  Move the DESERR_* table and
>          DES_FAILED deftypefun below cbc_crypt.  Move the entire
>          'getpass' section...
> 	* manual/terminal.texi: ...here.
> 
> 	* manual/random.texi: New file consolidating all discussion of
> 	random number generation.
> 	* manual/crypt.texi: 'Unpredictable Bytes' section moved to random.texi.
> 	* manual/math.texi: 'Pseudo-Random Numbers' section moved to
> 	random.texi.
> 	* manual/Makefile (chapters): Add 'random' after 'arith'.

I think this is okay.  I have not checked for no inadvertent changes in 
detail, though.

> 	* manual/arith.texi, manual/time.texi: Update chapter-level node
> 	pointers.

Do we still need to maintain node pointers manually?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/4] Reorganize manual sections on cryptography and random numbers.
  2018-05-08 13:29   ` Florian Weimer
@ 2018-05-08 13:37     ` Zack Weinberg
  2018-05-08 13:38       ` Florian Weimer
  0 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2018-05-08 13:37 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library, Carlos O'Donell, Rical Jasan

On Tue, May 8, 2018 at 9:29 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>         * manual/arith.texi, manual/time.texi: Update chapter-level node
>>         pointers.
>
> Do we still need to maintain node pointers manually?

Yes, unfortunately, libc-texinfo.sh needs them (that's the script that
generates the "top menu").

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/4] Reorganize manual sections on cryptography and random numbers.
  2018-05-08 13:37     ` Zack Weinberg
@ 2018-05-08 13:38       ` Florian Weimer
  0 siblings, 0 replies; 19+ messages in thread
From: Florian Weimer @ 2018-05-08 13:38 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library, Carlos O'Donell, Rical Jasan

On 05/08/2018 03:37 PM, Zack Weinberg wrote:
> On Tue, May 8, 2018 at 9:29 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>>          * manual/arith.texi, manual/time.texi: Update chapter-level node
>>>          pointers.
>>
>> Do we still need to maintain node pointers manually?
> 
> Yes, unfortunately, libc-texinfo.sh needs them (that's the script that
> generates the "top menu").

Oh, how unfortunate.  Well, I guess then this patch is okay as-is.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/4] Revise manual sections on cryptography and random numbers.
  2018-05-06 17:52 ` [PATCH 2/4] Revise manual sections on cryptography and random numbers Zack Weinberg
@ 2018-05-08 14:23   ` Florian Weimer
  2018-05-08 15:59     ` Zack Weinberg
  2018-05-09 11:36   ` Rical Jasan
  1 sibling, 1 reply; 19+ messages in thread
From: Florian Weimer @ 2018-05-08 14:23 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha; +Cc: carlos, rj

On 05/06/2018 07:51 PM, Zack Weinberg wrote:

> +@Theglibc{} is not a general-purpose cryptography library, but it does
> +include one-way hash functions for password storage, and a set of
> +encryption functions based on the obsolete DES block cipher.  The
> +latter are present for historical reasons only, and should not be used
> +at all anymore; any existing programs that still use them need to be
> +updated to use ciphers that are still secure.

Okay.

> +Many countries have historically placed legal restrictions on the
> +import, export, possession, or use of cryptographic tools.  These
> +restrictions change frequently, so we cannot give you specific advice
> +about what the situation might be in your country.  To the best of our
> +knowledge, no one has objected to the export or import of @theglibc{}
> +in many years,

I think people routinely file notices for glibc with the appropriate 
authorities.  The whole thing doesn't really work the way the text 
implies.  It's not that nobody complains, it's that all this work is 
done proactively.  I don't think we need to get into detail here.

> but if you are writing a program that performs
> +cryptographic operations, we advise you to find out what your
> +country's laws might be, first.  The one-way hash functions for
> +password storage are less likely to be restricted than the DES-based
> +encryption functions, because they cannot be used to send secret
> +messages---the recipient would not be able to decrypt them.

It's fairly easy to turn a one-way hash function into a stream cipher, 
so I'm not sure if the final sentence is correct.

The HMAC construction can also be used with this and give you a cipher:

   <https://people.csail.mit.edu/rivest/Chaffing.txt>

I'm also not sure if DES qualifies as a cryptographic algorithm anymore, 
so the actual situation might well be the opposite of what you state. 
Sorry.

> +Programs that handle passwords must take special care not to reveal
> +them to anyone, no matter what.  It is not enough to keep them in a
> +file that is only accessible with special privileges.  The file might
> +be ``leaked'' via a bug or misconfiguration, and system administrators
> +shouldn't learn everyone's password even if they have to edit that
> +file for some reason.  To avoid this, passwords should also be
> +converted into @dfn{one-way hashes}, using a @dfn{one-way function},
> +before they are stored.  It is believed that the only way to recover a
> +password from its one-way hash is to guess possible passwords, hash
> +them, and compare the output with the hashes stored in the password
> +file.  The one-way functions are designed to make this process
> +impractically slow, for all but the most obvious guesses.  (Do not use
> +a word from the dictionary as your password.)

Okay.

> +@Theglibc{} provides an interface to four different one-way functions,
> +based on the SHA-2-512, SHA-2-256, MD5, and DES cryptographic
> +primitives.  New passwords should be hashed with either of the
> +SHA-based functions.  The others are too weak for newly set passwords,
> +but we continue to support them for verifying old passwords.  The
> +DES-based hash is especially weak, because it ignores all but the
> +first eight characters of its input.

Okay.

> +The function @code{crypt} converts a password string, @var{phrase},
> +into a one-way hash suitable for storage in the user database.  The
> +hash will consist entirely of printable ASCII characters.  It will not
> +contain whitespace, nor any of the characters @kbd{:}, @kbd{;},
> +@kbd{*}, @kbd{!}, or @kbd{\}.

@code{':'} etc.?  These are bytes, not keyboard characters.

> +The @var{salt} parameter controls which one-way function is used, and
> +it also ensures that the output of the one-way function is different
> +for every user, even if they have the same password.  This makes it
> +harder to guess passwords from a large user database.  Without salt,
> +the intruder could make a guess, run @code{crypt} on it once, and
> +compare the result with all the hashed passwords.  Salt forces the
> +intruder to make many calls to @code{crypt} for each guess.

Okay.

> +To verify a password, pass the previously hashed password as the
> +@var{salt}.  To hash a new password for storage, set @var{salt} to a
> +string consisting of a prefix plus a sequence of randomly chosen
> +characters, according to this table:
> +
> +@multitable @columnfractions .15 .1 .3
> +@headitem Algorithm @tab Prefix @tab Random sequence
> +@item SHA-2-512
> +@tab @samp{$6$}
> +@tab 16 characters
> +@item SHA-2-256
> +@tab @samp{$5$}
> +@tab 16 characters
> +@item MD5
> +@tab @samp{$1$}
> +@tab 8 characters
> +@item DES
> +@tab @samp{}
> +@tab 2 characters
> +@end multitable

Maybe use @code{"$6$"} etc. for the prefixes?  No strong preference on 
my part though.

> +In all cases, the random characters should be chosen from the alphabet
> +@code{./0-9A-Za-z}.

The code checks this, right?  Or perhaps only for DES.

> +With all of the hash functions @emph{except} DES, @var{phrase} can be
> +arbitrarily long, and all eight bits of each byte are significant.
> +With DES, all but the first eight characters of @var{phrase} are ignored,
> +and the eighth bit of each byte is also ignored.

Okay.

> +@code{crypt} can fail.  Some implementations return @code{NULL} on
> +failure, and others return an @emph{invalid} hashed passphrase, which
> +will begin with a @kbd{*} and will not be the same as @var{salt}.  In

@code{'*'}?

> +either case, @code{errno} will be set to indicate the problem.  Some
> +of the possible error codes are:
> +
> +@table @code
> +@item EINVAL
> +@var{salt} is invalid; neither a previously hashed password, nor a
> +well-formed new salt for any of the supported hash functions.
> +
> +@item EPERM
> +The hash function selected by @var{salt} has been disabled by local
> +policy.
> +
> +@item ENOMEM
> +Failed to allocate internal scratch storage.
> +
> +@item ENOSYS
> +@itemx EOPNOTSUPP
> +Hashing passphrases is not supported at all, or the hash function
> +selected by @var{salt} is not supported.  @Theglibc{} does not use
> +these error codes, but they may be encountered on other operating
> +systems.
> +@end table
> +
> +@code{crypt} uses static storage for both internal scratchwork and the
> +string it returns.  It is not safe to call @code{crypt} from multiple
> +threads simultaneously, and the string it returns will be overwritten
> +by any subsequent call to @code{crypt}.

Okay.

> +@code{crypt} is specified in the X/Open Portability Guide and is
> +present on nearly all historical Unix systems.  However, XPG does not
> +specify any one-way functions.

> +@code{crypt} is declared in @file{unistd.h}.  @Theglibc{} also
> +declares this function in @file{crypt.h}.

Okay.

>   @end deftypefun
>   
> -@deftypefun {char *} crypt_r (const char *@var{key}, const char *@var{salt}, {struct crypt_data *} @var{data})
> +@deftypefun {char *} crypt_r (const char *@var{phrase}, const char *@var{salt}, {struct crypt_data *} @var{data})
>   @standards{GNU, crypt.h}
>   @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
>   @c Compared with crypt, this function fixes the @mtasurace:crypt
>   @c problem, but nothing else.
>   
> -The @code{crypt_r} function does the same thing as @code{crypt}, but
> -takes an extra parameter which includes space for its result (among
> -other things), so it can be reentrant.  @code{data@w{->}initialized} must be
> -cleared to zero before the first time @code{crypt_r} is called.
> -
> -The @code{crypt_r} function is a GNU extension.
> +The function @code{crypt_r} is a reentrant version of @code{crypt}.

I don't think crypt_r is reentrant, it is merely thread-safe.  But no 
strong opinion.

> +Instead of static storage, it uses the memory pointed to by its
> +@var{data} argument for both scratchwork and the string it returns.
> +It can safely be used from multiple threads, as long as different
> +@var{data} objects are used in each thread.  The string it returns
> +will still be overwritten by another call with the same @var{data}.
> +@var{data} must be a pointer to a @samp{struct crypt_data} object
> +allocated by the caller, and before one of these objects is used for
> +the first time, it must be erased using
> +@samp{@w{memset(data, 0, sizeof data)}}
> +or similar.

Missing space before parentheses.

Perhaps add a warning that struct crypt_data is very large and should 
not be allocated on the stack?

> +The following program shows how to use @code{crypt} the first time a
> +password is entered.  It uses @code{getentropy} to make the salt as
> +unpredictable as possible; @pxref{Unpredictable Bytes}.

Okay.

>   @smallexample
>   @include genpass.c.texi
>   @end smallexample
>   
> -The next program shows how to verify a password.  It prompts the user
> -for a password and prints ``Access granted.'' if the user types
> -@code{GNU libc manual}.
> +@c When we have documentation for getspnam, change the demo to use it.
> +The next program shows how to verify a password stored in the system
> +user database in the traditional manner; @pxref{User Database}.  (On
> +newer installations, the passwords are instead stored in a ``shadow''
> +database that requires special privileges to access, and this program
> +will not work.)

Okay.

> +@node Obsolete Encryption
> +@section Obsolete Encryption
> +
> +For historical reasons, @theglibc{} includes several functions which
> +perform encryption using the obsolete Data Encryption Standard (DES).
> +None of these functions should be used anymore.  Instead, use one of
> +the many free encryption libraries that use modern ciphers.

Okay.  Maybe also say that these functions are not thread-safe?

> +DES is a block cipher standardized by the US government in 1977.  It
> +is no longer considered to be secure, and has been withdrawn as a
> +standard, because it only has @math{2@sup{56}} possible keys, so
> +testing all of them is practical.  In 1998, it cost US$250,000 to
> +build a massively parallel computer that could find the DES key that
> +encrypted a known message in three days.  In 2018, the same process
> +takes only one day, and there are online services that will do it for
> +less than US$100 per message.

Okay.

> +The @code{setkey} function prepares to perform DES encryption or
> +decryption using the key @var{key}.  @var{key} should point to an
> +array of 64 @code{char}s, each of which must be set to either @samp{0}
> +or @samp{1}; that is, each byte stores one bit of the key.  Every
> +eighth byte (array indices 7, 15, 23, @dots{}) must be set to give it
> +plus the preceding group of seven bytes odd parity.

“must be set to the negation of the parity of the preceding seven 
bits/bytes”?

>  For instance, if
> +there are three bytes set to @samp{1} among bytes 0 through 6, then
> +byte 7 must be set to @samp{0}, and similarly if there are four bytes
> +set to @samp{1} among bytes 8 through 14, then byte 15 must be set to
> +@samp{0}, and so on.  Thus, of the 64 bytes, only 56 can be used to
> +supply key data.

Okay.

> +The @code{setkey} function is specified in the X/Open Portability
> +Guide and is declared in @file{stdlib.h}.  @Theglibc{} also declares
> +this function in @file{crypt.h}.
>   @end deftypefun

Okay.

>   @deftypefun void encrypt (char *@var{block}, int @var{edflag})
> -@standards{BSD, crypt.h}
> -@standards{SVID, crypt.h}
> +@standards{X/Open, unistd.h}
> +@standards{GNU, crypt.h}
>   @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
>   @c Same issues as setkey.
>   
> -The @code{encrypt} function encrypts @var{block} if
> -@var{edflag} is 0, otherwise it decrypts @var{block}, using a key
> -previously set by @code{setkey}.  The result is
> -placed in @var{block}.
> +The @code{encrypt} function encrypts @var{block} if @var{edflag} is 0,
> +otherwise it decrypts @var{block}, using a key previously set by
> +@code{setkey}.  The result overwrites the previous value of
> +@var{block}.
>   
> -Like @code{setkey}, @var{block} is specified as an array of 64 bits each
> -stored in a @code{char}, but there are no parity bits in @var{block}.
> +Like @code{setkey}, @var{block} is as an array of 64 @code{char}s,
> +each of which stores one bit of the block to be encrypted.  Unlike
> +@code{setkey}, there are no parity bits.  All 64 of the bits are
> +treated as data.
> +
> +The @code{encrypt} function is specified in the X/Open Portability
> +Guide and is declared in @file{unistd.h}.  @Theglibc{} also declares
> +this function in @file{crypt.h}.

Okay.

> @@ -245,25 +267,30 @@ stored in a @code{char}, but there are no parity bits in @var{block}.
>   These are reentrant versions of @code{setkey} and @code{encrypt}.  The
>   only difference is the extra parameter, which stores the expanded
>   version of @var{key}.  Before calling @code{setkey_r} the first time,
> -@code{data->initialized} must be cleared to zero.
> -@end deftypefun
> +@code{data} must be erased using
> +@samp{@w{memset(data, 0, sizeof data)}}
> +or similar.

Missing space before parenthesis.

> -The @code{setkey_r} and @code{encrypt_r} functions are GNU extensions.
> -@code{setkey}, @code{encrypt}, @code{setkey_r}, and @code{encrypt_r} are
> -defined in @file{crypt.h}.
> +@code{setkey_r} and @code{encrypt_r} are GNU extensions.  They are
> +declared in @file{crypt.h}.
> +@end deftypefun
>   
>   @deftypefun int ecb_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode})
>   @standards{SUNRPC, rpc/des_crypt.h}
>   @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>   
>   The function @code{ecb_crypt} encrypts or decrypts one or more blocks
> -using DES.  Each block is encrypted independently.
> +using DES.  Each block is encrypted independently, which means that if
> +any two input blocks are the same, then their encryptions will also be
> +the same.  This is an additional weakness in the encryption, on top of
> +the weakness of DES itself.

Maybe mention Electronic Codebook Mode (ECB)?

>   The @var{blocks} and the @var{key} are stored packed in 8-bit bytes, so
>   that the first bit of the key is the most-significant bit of
>   @code{key[0]} and the 63rd bit of the key is stored as the
> -least-significant bit of @code{key[7]}.  The @var{key} should have the
> -correct parity.
> +least-significant bit of @code{key[7]}.  The least-significant bit of
> +each byte must be chosen to give each byte odd parity, as with
> +@code{setkey}.

Okay.

>   @var{len} is the number of bytes in @var{blocks}.  It should be a
>   multiple of 8 (so that there are a whole number of blocks to encrypt).
> @@ -271,33 +298,33 @@ multiple of 8 (so that there are a whole number of blocks to encrypt).
>   
>   The result of the encryption replaces the input in @var{blocks}.
>   
> -The @var{mode} parameter is the bitwise OR of two of the following:
> +The @var{mode} parameter should be the bitwise OR of one of these two
> +constants:
>   
>   @vtable @code
>   @item DES_ENCRYPT
>   @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, specifies that
>   @var{blocks} is to be encrypted.
>   
>   @item DES_DECRYPT
>   @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, specifies that
>   @var{blocks} is to be decrypted.
> +@end vtable

Okay.

> +@noindent
> +with one of these two constants:
>   
> +@vtable @code
>   @item DES_HW
>   @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, asks to use a hardware
> -device.  If no hardware device is available, encryption happens anyway,
> -but in software.
> +Use a hardware DES accelerator, if available.  If no accelerator is
> +available, encryption or decryption will still occur, but in software.
>   
>   @item DES_SW
>   @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, specifies that no
> -hardware device is to be used.
> +Do not use a hardware DES accelerator.
>   @end vtable

Okay.

>   @deftypefun int cbc_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode}, char *@var{ivec})
>   @standards{SUNRPC, rpc/des_crypt.h}
>   @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> @@ -324,7 +351,8 @@ bytes.
>   Otherwise, all the parameters are similar to those for @code{ecb_crypt}.
>   @end deftypefun
>   
> -The result of the function will be one of these values:
> +@code{ecb_crypt} and @code{cbc_crypt} both return one of the following
> +values:
>   
>   @vtable @code
>   @item DESERR_NONE
> @@ -333,7 +361,7 @@ The encryption succeeded.
>   
>   @item DESERR_NOHWDEVICE
>   @standards{SUNRPC, rpc/des_crypt.h}
> -The encryption succeeded, but there was no hardware device available.
> +The encryption succeeded, but there was no hardware accelerator available.
>   
>   @item DESERR_HWERROR
>   @standards{SUNRPC, rpc/des_crypt.h}
> @@ -344,13 +372,20 @@ The encryption failed because of a hardware problem.
>   The encryption failed because of a bad parameter, for instance @var{len}
>   is not a multiple of 8 or @var{len} is larger than @code{DES_MAXDATA}.
>   @end vtable
> +@end deftypefun

Okay.

> +For convenience, there is a macro which distinguishes successful from
> +failure result codes:
>   
> -@deftypefun int DES_FAILED (int @var{err})
> +@deftypefn Macro int DES_FAILED (int @var{err})
>   @standards{SUNRPC, rpc/des_crypt.h}
>   @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> -This macro returns 1 if @var{err} is a `success' result code from
> -@code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
> -@end deftypefun
> +This macro returns a nonzero value if @var{err} is a failure result
> +code from @code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
> +@end deftypefn
> +
> +There is also a helper function which assists in producing well-formed
> +DES keys:

Okay.

>   @deftypefun void des_setparity (char *@var{key})
>   @standards{SUNRPC, rpc/des_crypt.h}
> diff --git a/manual/examples/genpass.c b/manual/examples/genpass.c
> index 5edb2e9b8a..fe10a847cf 100644
> --- a/manual/examples/genpass.c
> +++ b/manual/examples/genpass.c
> @@ -16,34 +16,44 @@
>   */
>   
>   #include <stdio.h>
> -#include <time.h>
>   #include <unistd.h>
>   #include <crypt.h>
>   
>   int
>   main(void)
>   {
> -  unsigned long seed[2];
> -  char salt[] = "$1$........";
> -  const char *const seedchars =
> +  unsigned char ubytes[16];
> +  char salt[20];
> +  const char *const saltchars =
>       "./0123456789ABCDEFGHIJKLMNOPQRST"
>       "UVWXYZabcdefghijklmnopqrstuvwxyz";
>     char *password;
>     int i;
>   
> -  /* Generate a (not very) random seed.
> -     You should do it better than this...  */
> -  seed[0] = time(NULL);
> -  seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
> -
> -  /* Turn it into printable characters from `seedchars'.  */
> -  for (i = 0; i < 8; i++)
> -    salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
> +  /* Retrieve 16 unpredictable bytes from the operating system.  */
> +  if (getentropy (ubytes, sizeof ubytes))
> +    {
> +      perror ("getentropy");
> +      return 1;
> +    }

Explicit check of getentropy return value against zero?  It's not 
exactly a boolean flag, after all.

> +
> +  /* Use them to fill in the salt string.  */
> +  salt[0] = '$';
> +  salt[1] = '5'; /* SHA-256 */
> +  salt[2] = '$';
> +  for (i = 0; i < 16; i++)
> +    salt[3+i] = saltchars[ubytes[i] & 0x3f];
> +  salt[19] = '\0';
>   
>     /* Read in the user's password and encrypt it.  */
> -  password = crypt(getpass("Password:"), salt);
> +  password = crypt (getpass ("Password:"), salt);
> +  if (!password)
> +    {
> +      perror ("crypt");
> +      return 1;
> +    }
>   
>     /* Print the results.  */
> -  puts(password);
> +  puts (password);
>     return 0;
>   }

Okay.

> diff --git a/manual/examples/testpass.c b/manual/examples/testpass.c
> index 19f1ae7de0..3cc2383ea8 100644
> --- a/manual/examples/testpass.c
> +++ b/manual/examples/testpass.c
> @@ -15,29 +15,45 @@
>      along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
>   */
>   
> +#include <sys/types.h>
> +#include <pwd.h>
>   #include <stdio.h>
>   #include <string.h>
>   #include <unistd.h>
>   #include <crypt.h>
>   
>   int
> -main(void)
> +main(int argc, char **argv)
>   {
> -  /* Hashed form of "GNU libc manual".  */
> -  const char *const pass = "$1$/iSaq7rB$EoUw5jJPPvAPECNaaWzMK/";
> -
>     char *result;
>     int ok;
> +  struct passwd *pw;
> +
> +  if (argc < 2)
> +    {
> +      fprintf (stderr, "usage: %s username\n", argv[0]);
> +      return 1;
> +    }
> +
> +  /* Retrieve the password for user argv[1]
> +     from the user database.  */
> +  pw = getpwnam (argv[1]);

Check error?

> -/*@group*/
>     /* Read in the user's password and encrypt it,
>        passing the expected password in as the salt.  */
> -  result = crypt(getpass("Password:"), pass);
> -/*@end group*/
> +  result = crypt (getpass ("Password:"), pw->pw_passwd);
> +  if (!result)
> +    {
> +      perror ("crypt");
> +      return 1;
> +    }
> +
> +  printf ("Stored:  %s\n", pw->pw_passwd);
> +  printf ("Current: %s\n", result);
>   
>     /* Test the result.  */
> -  ok = strcmp (result, pass) == 0;
> +  ok = strcmp (result, pw->pw_passwd) == 0;

Maybe add a comment that this could result in a timing oracle?

> -  puts(ok ? "Access granted." : "Access denied.");
> +  puts (ok ? "Access granted." : "Access denied.");
>     return ok ? 0 : 1;
>   }
> diff --git a/manual/random.texi b/manual/random.texi
> index c53ed7fc22..c68a43aca0 100644
> --- a/manual/random.texi
> +++ b/manual/random.texi
> @@ -2,6 +2,52 @@
>   @chapter Random Number Generation
>   @c %MENU% Various ways to generate random values.
>   
> +Many algorithms require a source of @dfn{random numbers}, or to be
> +more precise, sequences of numbers chosen uniformly at random from
> +some subset of the integers or reals.  There are several different
> +ways to generate random numbers, depending on how stringent your
> +requirements are.
> +
> +A @dfn{pseudo-random number generator} (PRNG) produces a sequence of
> +numbers that @emph{appears} to be random, and has statistical
> +properties matching what we expect of numbers chosen uniformly at
> +random.  However, an ordinary PRNG doesn't guarantee that its output
> +is unguessable.  Also, the output of a PRNG depends on a relatively
> +small @dfn{seed} value, and so there are only a small number of
> +sequences that it can produce; astronomically small, relative to the
> +total number of random sequences.  If the seed is reused, the output
> +will be exactly the same, which is sometimes exactly what you want,
> +and sometimes disastrous.

Okay.

> +A @dfn{cryptographically strong pseudo-random number generator}
> +(CSPRNG) is a PRNG that @emph{does} guarantee its output is
> +unguessable.  Formally, there is no deterministic, polynomial-time
> +algorithm@footnote{Assuming
> +@iftex
> +@c Don't typeset NP as if multiplying N by P. Use text italic for both.
> +@math{\hbox{\it P} \neq \hbox{\it NP}}@c
> +@end iftex
> +@ifnottex
> +@math{P ≠ NP}@c
> +@end ifnottex
> +.} that can tell the difference between the output of
> +a CSPRNG and a sequence of numbers that really were chosen uniformly
> +at random.  A CSPRNG still uses a seed and can only produce an
> +astronomically small number of random sequences.

I'm not sure if this detail is necessary.  If it is, you need to add 
“independent” somewhere.

> +Finally, a @dfn{true random number generator} (TRNG) produces random
> +numbers not from a seed, but from some unpredictable physical process.
> +In principle, a TRNG's output is unguessable, and is not limited to an
> +astronomically small number of sequences.  However, TRNGs are very
> +slow, and because there is no seed, there is no way to make one repeat
> +its output.  Usually, it is best to use a TRNG only to choose the seed
> +for a PRNG or CSPRNG.
> +
> +At present, @theglibc{} offers a variety of ordinary PRNGs, and on
> +some operating systems it also offers access to an OS-provided TRNG.
> +We may add a CSPRNG in the future.

If this refers to arc4random, I don't think it's a CSPRNG under your 
definition.  And we shouldn't claim it has formal properties initially 
because that would make glibc subject to FIPS certification again, which 
is something we should avoid.

> +
> +
>   @menu
>   * Pseudo-Random Numbers::       Sequences of numbers with apparently
>                                    random distribution, but not difficult
> @@ -30,8 +76,7 @@ is convenient when you are debugging a program, but it is unhelpful if
>   you want the program to behave unpredictably.  If you want a different
>   pseudo-random series each time your program runs, you must specify a
>   different seed each time.  For ordinary purposes, basing the seed on the
> -current time works well.  For random numbers in cryptography,
> -@pxref{Unpredictable Bytes}.
> +current time works well.

Okay.

> @@ -595,14 +640,18 @@ programs.
>   @node Unpredictable Bytes
>   @section Generating Unpredictable Bytes
>   
> -Some cryptographic applications (such as session key generation) need
> -unpredictable bytes.
> +Some cryptographic applications need truly unpredictable bytes.
> +@Theglibc{} provides two functions for this purpose, both of which
> +access a true random generator implemented by the operating system.

I don't think the Linux urandom generator qualifies as a TRNG, sorry.

> +Not all operating systems support these functions; programs that use
> +them must be prepared for them to fail.  They are slow, and can only
> +produce short sequences of unpredictable bytes.  Most programs should
> +use these functions only to seed a cryptographically strong
> +pseudo-random generator.

The functions aren't *that* slow .  But I don't have a proposal for 
improving the wording.

> -In general, application code should use a deterministic random bit
> -generator, which could call the @code{getentropy} function described
> -below internally to obtain randomness to seed the generator.  The
> -@code{getrandom} function is intended for low-level applications which
> -need additional control over the blocking behavior.
> +Most programs should use @code{getentropy}.  The @code{getrandom}
> +function is intended for low-level applications which need additional
> +control over the blocking behavior.

Okay.

>   @deftypefun int getentropy (void *@var{buffer}, size_t @var{length})
>   @standards{GNU, sys/random.h}
> @@ -623,7 +672,9 @@ will keep blocking even if a signal arrives, and return only after the
>   entropy pool has been initialized.
>   
>   The @code{getentropy} function can fail with several errors, some of
> -which are listed below.
> +which are listed below.  Applications must check for failure.
> +However, when it succeeds, it will always produce exactly @var{length}
> +bytes of random data.

Okay.

> @@ -645,11 +696,11 @@ could not be overwritten with random data for an unspecified reason.
>   @standards{GNU, sys/random.h}
>   @safety{@mtsafe{}@assafe{}@acsafe{}}
>   
> -This function writes @var{length} bytes of random data to the array
> -starting at @var{buffer}.  On success, this function returns the number
> -of bytes which have been written to the buffer (which can be less than
> -@var{length}).  On error, @code{-1} is returned, and @code{errno} is
> -updated accordingly.
> +This function writes up to @var{length} bytes of random data to the
> +array starting at @var{buffer}.  On success, this function returns the
> +number of bytes which have been written to the buffer, which can be
> +less than @var{length}.  On error, @code{-1} is returned, and
> +@code{errno} is updated accordingly.

Okay.

>   The @code{getrandom} function is declared in the header file
>   @file{sys/random.h}.  It is a GNU extension.
> @@ -676,7 +727,8 @@ booted and the pool has not yet been initialized.
>   
>   The @code{getrandom} function can fail with several errors, some of
>   which are listed below.  In addition, the function may not fill the
> -buffer completely and return a value less than @var{length}.
> +buffer completely.  Applications must check for failure and for short
> +writes.

Okay.

>   @table @code
>   @item ENOSYS
> diff --git a/manual/string.texi b/manual/string.texi
> index b07cfb4550..f113777f2d 100644
> --- a/manual/string.texi
> +++ b/manual/string.texi
> @@ -2469,8 +2469,6 @@ Unlike Rot13, @code{memfrob} works on arbitrary binary data, not just
>   text.
>   @cindex Rot13
>   
> -For true encryption, @xref{Cryptographic Functions}.
> -

Okay.

>   This function is declared in @file{string.h}.
>   @pindex string.h
>   
> @@ -2487,9 +2485,7 @@ Note that @code{memfrob} a second time on the same data structure
>   returns it to its original state.
>   
>   This is a good function for hiding information from someone who doesn't
> -want to see it or doesn't want to see it very much.  To really prevent
> -people from retrieving the information, use stronger encryption such as
> -that described in @xref{Cryptographic Functions}.
> +want to see it or doesn't want to see it very much.

Hmm.  Okay I guess.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/4] Deprecate DES encryption functions.
  2018-05-06 17:51 ` [PATCH 3/4] Deprecate DES encryption functions Zack Weinberg
@ 2018-05-08 14:33   ` Florian Weimer
  2018-05-08 15:24     ` Zack Weinberg
  0 siblings, 1 reply; 19+ messages in thread
From: Florian Weimer @ 2018-05-08 14:33 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha; +Cc: carlos, rj

On 05/06/2018 07:51 PM, Zack Weinberg wrote:

> +* The functions 'encrypt', 'encrypt_r', 'setkey', 'setkey_r', 'cbc_crypt',
> +  'ecb_crypt', and 'des_setparity' are deprecated.  They encrypt and decrypt
> +  data with the DES block cipher, which is no longer considered secure.
> +  Also, encrypt, encrypt_r, setkey, and setkey_r require awkward pre- and
> +  post-processing of the encryption key and data to be encrypted, and
> +  encrypt and setkey are not thread-safe.  Software that still uses these
> +  functions should switch to a modern cryptography library, such as GnuTLS.

GNUTLS is no longer part of the GNU project.  You should recommend 
libgcrypt instead.

>   Changes to build and runtime requirements:
>   
>     [Add changes to build and runtime requirements here]
> diff --git a/crypt/Makefile b/crypt/Makefile
> index 303800df73..e122bcebf0 100644
> --- a/crypt/Makefile
> +++ b/crypt/Makefile
> @@ -32,6 +32,9 @@ libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
>   
>   tests := cert md5c-test sha256c-test sha512c-test badsalttest
>   
> +# cert.c tests the deprecated setkey/encrypt interface
> +CFLAGS-cert.c = -Wno-deprecated-declarations

Okay.

>   ifeq ($(crypt-in-libc),yes)
>   routines += $(libcrypt-routines)
>   endif
> diff --git a/crypt/crypt.h b/crypt/crypt.h
> index 5da098b715..22cf13ff89 100644
> --- a/crypt/crypt.h
> +++ b/crypt/crypt.h
> @@ -32,13 +32,18 @@ __BEGIN_DECLS
>   extern char *crypt (const char *__key, const char *__salt)
>        __THROW __nonnull ((1, 2));
>   
> -/* Setup DES tables according KEY.  */
> -extern void setkey (const char *__key) __THROW __nonnull ((1));
> +/* Set the encryption key for subsequent calls to 'encrypt'.
> +   This function should not be used in new programs, because the cipher
> +   it uses is DES, which is unacceptably weak by modern standards.  */
> +extern void setkey (const char *__key)
> +     __THROW __nonnull ((1)) __attribute_deprecated__;
>   
>   /* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
> -   block in place.  */
> +   block in place.  The key is controlled by 'setkey'.
> +   This function should not be used in new programs, because the cipher
> +   it uses is DES, which is unacceptably weak by modern standards.  */
>   extern void encrypt (char *__glibc_block, int __edflag)
> -     __THROW __nonnull ((1));
> +     __THROW __nonnull ((1)) __attribute_deprecated__;
>   
>   #ifdef __USE_GNU
>   /* Reentrant versions of the functions above.  The additional argument
> @@ -63,11 +68,11 @@ extern char *crypt_r (const char *__key, const char *__salt,
>   
>   extern void setkey_r (const char *__key,
>   		      struct crypt_data * __restrict __data)
> -     __THROW __nonnull ((1, 2));
> +     __THROW __nonnull ((1, 2)) __attribute_deprecated__;
>   
>   extern void encrypt_r (char *__glibc_block, int __edflag,
>   		       struct crypt_data * __restrict __data)
> -     __THROW __nonnull ((1, 3));
> +     __THROW __nonnull ((1, 3)) __attribute_deprecated__;
>   #endif

Okay.

>   __END_DECLS
> diff --git a/posix/unistd.h b/posix/unistd.h
> index 4d149f9945..5d4e07f6c8 100644
> --- a/posix/unistd.h
> +++ b/posix/unistd.h
> @@ -1127,10 +1127,12 @@ extern char *crypt (const char *__key, const char *__salt)
>        __THROW __nonnull ((1, 2));
>   
>   /* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
> -   block in place.  */
> -extern void encrypt (char *__glibc_block, int __edflag)
> -     __THROW __nonnull ((1));
> +   block in place.  The key is controlled by 'setkey', in stdlib.h.
>   
> +   This function should not be used in new programs, because the cipher
> +   it uses is DES, which is unacceptably weak by modern standards.  */
> +extern void encrypt (char *__glibc_block, int __edflag)
> +     __THROW __nonnull ((1)) __attribute_deprecated__;

Okay.

>   
>   /* Swab pairs bytes in the first N bytes of the area pointed to by
>      FROM and copy the result to TO.  The value of TO must not be in the
> diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
> index 6b1ead31e0..5b104bcc51 100644
> --- a/stdlib/stdlib.h
> +++ b/stdlib/stdlib.h
> @@ -959,8 +959,13 @@ extern int getsubopt (char **__restrict __optionp,
>   
>   
>   #ifdef __USE_XOPEN
> -/* Setup DES tables according KEY.  */
> -extern void setkey (const char *__key) __THROW __nonnull ((1));
> +/* Set the encryption key for subsequent calls to 'encrypt', which is
> +   declared in unistd.h.
> +
> +   This function should not be used in new programs, because the cipher
> +   it uses is DES, which is unacceptably weak by modern standards.  */
> +extern void setkey (const char *__key)
> +     __THROW __nonnull ((1)) __attribute_deprecated__;
>   #endif

Okay.

> diff --git a/sunrpc/Makefile b/sunrpc/Makefile
> index 8f2a3c8213..07fb90de6b 100644
> --- a/sunrpc/Makefile
> +++ b/sunrpc/Makefile
> @@ -156,6 +156,15 @@ CFLAGS-pmap_rmt.c += -fexceptions
>   CFLAGS-clnt_perr.c += -fexceptions
>   CFLAGS-openchild.c += -fexceptions
>   
> +# These files implement Secure RPC authentication using DES, which is
> +# no longer secure and has had some of the associated functions tagged
> +# __attribute_deprecated__.
> +CFLAGS-auth_des.c += -Wno-deprecated-declarations
> +CFLAGS-des_crypt.c += -Wno-deprecated-declarations
> +CFLAGS-des_soft.c += -Wno-deprecated-declarations
> +CFLAGS-svcauth_des.c += -Wno-deprecated-declarations
> +CFLAGS-xcrypt.c += -Wno-deprecated-declarations
> +

Okay.

>   sunrpc-CPPFLAGS = -D_RPC_THREAD_SAFE_
>   CPPFLAGS += $(sunrpc-CPPFLAGS)
>   BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS)
> diff --git a/sunrpc/rpc/des_crypt.h b/sunrpc/rpc/des_crypt.h
> index 77cca3cbed..85875afa11 100644
> --- a/sunrpc/rpc/des_crypt.h
> +++ b/sunrpc/rpc/des_crypt.h
> @@ -70,6 +70,10 @@ __BEGIN_DECLS
>    * DESERR_NOHWDEVICE is returned if DES_HW was specified but
>    * there was no hardware to do it on (the data will still be
>    * encrypted though, in software).
> + *
> + * None of the functions in this header should be used in new programs,
> + * because the cipher they use is DES, which is unacceptably weak by
> + * modern standards.
>    */
>   
>   
> @@ -77,19 +81,20 @@ __BEGIN_DECLS
>    * Cipher Block Chaining mode
>    */
>   extern int cbc_crypt (char *__key, char *__buf, unsigned __len,
> -		      unsigned __mode, char *__ivec) __THROW;
> +		      unsigned __mode, char *__ivec)
> +  __THROW __attribute_deprecated__;
>   
>   /*
>    * Electronic Code Book mode
>    */
>   extern int ecb_crypt (char *__key, char *__buf, unsigned __len,
> -		      unsigned __mode) __THROW;
> +		      unsigned __mode) __THROW __attribute_deprecated__;
>   
>   /*
>    * Set des parity for a key.
>    * DES parity is odd and in the low bit of each byte
>    */
> -extern void des_setparity (char *__key) __THROW;
> +extern void des_setparity (char *__key) __THROW __attribute_deprecated__;

Okay.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/4] New configure option --disable-crypt.
  2018-05-06 17:52 ` [PATCH 4/4] New configure option --disable-crypt Zack Weinberg
@ 2018-05-08 15:00   ` Florian Weimer
  2018-05-08 15:22     ` Zack Weinberg
  0 siblings, 1 reply; 19+ messages in thread
From: Florian Weimer @ 2018-05-08 15:00 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha; +Cc: carlos, rj

On 05/06/2018 07:51 PM, Zack Weinberg wrote:
> diff --git a/INSTALL b/INSTALL
> index 052b1b6f89..6de609c9d6 100644
> --- a/INSTALL
> +++ b/INSTALL
> @@ -197,6 +197,17 @@ if 'CFLAGS' is specified it must enable optimization.  For example:
>        libnss_nisplus are not built at all.  Use this option to enable
>        libnsl with all depending NSS modules and header files.
>   
> +'--disable-crypt'
> +     Do not install the password-hashing library 'libcrypt' or the
> +     header file 'crypt.h'.  'unistd.h' will still declare the function
> +     'crypt', as required by POSIX. Using this option does not change
> +     the set of programs that may need to be linked with '-lcrypt'; it
> +     only means that the GNU C Library will not provide that library.

Two spaces after dot; see below.

> +     This option is for hackers and distributions experimenting with
> +     independently-maintained implementations of libcrypt.  It may
> +     become the default in a future release.

Okay.

> diff --git a/Makeconfig b/Makeconfig
> index 1afe86475c..608ffe648c 100644
> --- a/Makeconfig
> +++ b/Makeconfig
> @@ -566,7 +566,7 @@ link-libc-printers-tests = $(link-libc-rpath) \
>   			   $(link-libc-tests-after-rpath-link)
>   
>   # This is how to find at build-time things that will be installed there.
> -rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec support
> +rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support
>   rpath-link = \
>   $(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
>   else  # build-static
> @@ -1205,9 +1205,14 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal	    \
>   	      stdlib stdio-common libio malloc string wcsmbs time dirent    \
>   	      grp pwd posix io termios resource misc socket sysvipc gmon    \
>   	      gnulib iconv iconvdata wctype manual shadow gshadow po argp   \
> -	      crypt localedata timezone rt conform debug mathvec support    \
> +	      localedata timezone rt conform debug mathvec support	    \
>   	      dlfcn elf
>   
> +ifeq ($(build-crypt),yes)
> +all-subdirs += crypt
> +rpath-dirs += crypt
> +endif

Okay.

>   ifndef avoid-generated
>   # sysd-sorted itself will contain rules making the sysd-sorted target
>   # depend on Depend files.  But if you just added a Depend file to an
> diff --git a/NEWS b/NEWS
> index 2fe2da8b59..cfc58f71bb 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -71,6 +71,18 @@ Deprecated and removed features, and other changes affecting compatibility:
>     encrypt and setkey are not thread-safe.  Software that still uses these
>     functions should switch to a modern cryptography library, such as GnuTLS.
>   
> +* We have tentative plans to deprecate glibc's implementation of the
> +  password-hashing functions 'crypt' and 'crypt_r'.  We will continue
> +  to declare crypt in <unistd.h>, as required by POSIX, and programs
> +  that use crypt or crypt_r should not need to change at all.  However,
> +  the header file <crypt.h> and library libcrypt.{a,so} will come from
> +  a separate development project that will, we hope, keep up better with
> +  new password-hashing algorithms.
> +
> +  In this release, if the configure option --disable-crypt is used,
> +  glibc will not install <crypt.h> or libcrypt.  The plan is to make
> +  this the default behavior in a future release.

Okay.

> diff --git a/config.make.in b/config.make.in
> index 9e5e24b2c6..d9891b2cd8 100644
> --- a/config.make.in
> +++ b/config.make.in
> @@ -96,6 +96,7 @@ cross-compiling = @cross_compiling@
>   force-install = @force_install@
>   link-obsolete-rpc = @link_obsolete_rpc@
>   build-obsolete-nsl = @build_obsolete_nsl@
> +build-crypt = @build_crypt@
>   build-nscd = @build_nscd@
>   use-nscd = @use_nscd@
>   build-hardcoded-path-in-tests= @hardcoded_path_in_tests@

Okay.

> diff --git a/configure b/configure
> index 7a8bd3f817..7317c1aee4 100755
> --- a/configure
> +++ b/configure

Okay (generated file).

> diff --git a/configure.ac b/configure.ac
> index ca1282a6b3..05e03f2f72 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -302,11 +302,22 @@ AC_ARG_ENABLE([experimental-malloc],
>   	      [experimental_malloc=yes])
>   AC_SUBST(experimental_malloc)
>   
> +AC_ARG_ENABLE([crypt],
> +              AC_HELP_STRING([--disable-crypt],
> +                             [do not build nor install the password hashing library, libcrypt]),
> +              [build_crypt=$enableval],
> +              [build_crypt=yes])
> +AC_SUBST(build_crypt)

Okay.

>   AC_ARG_ENABLE([nss-crypt],
>   	      AC_HELP_STRING([--enable-nss-crypt],
>   			     [enable libcrypt to use nss]),
>   	      [nss_crypt=$enableval],
>   	      [nss_crypt=no])
> +if test x$build_libcrypt = xno && test x$nss_crypt = xyes; then
> +  AC_MSG_WARN([--enable-nss-crypt has no effect when libcrypt is disabled])
> +  nss_crypt=no
> +fi

Okay.

>   if test x$nss_crypt = xyes; then
>     nss_includes=-I$(nss-config --includedir 2>/dev/null)
>     if test $? -ne 0; then
> diff --git a/conform/Makefile b/conform/Makefile
> index 864fdeca21..74fbda0786 100644
> --- a/conform/Makefile
> +++ b/conform/Makefile
> @@ -193,13 +193,11 @@ linknamespace-libs-thr = $(linknamespace-libs-isoc) \
>   			 $(common-objpfx)rt/librt.a $(static-thread-library)
>   linknamespace-libs-posix = $(linknamespace-libs-thr) \
>   			   $(common-objpfx)dlfcn/libdl.a
> -linknamespace-libs-xsi = $(linknamespace-libs-posix) \
> -			 $(common-objpfx)crypt/libcrypt.a
> +linknamespace-libs-xsi = $(linknamespace-libs-posix)
>   linknamespace-libs-ISO = $(linknamespace-libs-isoc)
>   linknamespace-libs-ISO99 = $(linknamespace-libs-isoc)
>   linknamespace-libs-ISO11 = $(linknamespace-libs-isoc)
> -linknamespace-libs-XPG4 = $(linknamespace-libs-isoc) \
> -			  $(common-objpfx)crypt/libcrypt.a
> +linknamespace-libs-XPG4 = $(linknamespace-libs-isoc)
>   linknamespace-libs-XPG42 = $(linknamespace-libs-XPG4)
>   linknamespace-libs-POSIX = $(linknamespace-libs-thr)
>   linknamespace-libs-UNIX98 = $(linknamespace-libs-xsi)
> @@ -209,6 +207,11 @@ linknamespace-libs-XOPEN2K8 = $(linknamespace-libs-xsi)
>   linknamespace-libs = $(foreach std,$(conformtest-standards),\
>   				   $(linknamespace-libs-$(std)))
>   
> +ifeq ($(build-crypt),yes)
> +linknamespace-libs-xsi += $(common-objpfx)crypt/libcrypt.a
> +linknamespace-libs-XPG4 += $(common-objpfx)crypt/libcrypt.a
> +endif
> +

Okay.

>   $(linknamespace-symlist-stdlibs-tests): $(objpfx)symlist-stdlibs-%: \
>   					$(linknamespace-libs)
>   	LC_ALL=C $(READELF) -W -s $(linknamespace-libs-$*) > $@; \
> diff --git a/crypt/Makefile b/crypt/Makefile
> index e122bcebf0..1e2f21bf52 100644
> --- a/crypt/Makefile
> +++ b/crypt/Makefile
> @@ -35,10 +35,6 @@ tests := cert md5c-test sha256c-test sha512c-test badsalttest
>   # cert.c tests the deprecated setkey/encrypt interface
>   CFLAGS-cert.c = -Wno-deprecated-declarations
>   
> -ifeq ($(crypt-in-libc),yes)
> -routines += $(libcrypt-routines)
> -endif
> -

Okay.

>   ifeq ($(nss-crypt),yes)
>   nss-cpp-flags := -DUSE_NSS \
>     -I$(shell nss-config --includedir) -I$(shell nspr-config --includedir)
> diff --git a/crypt/crypt.h b/crypt/crypt.h
> index 22cf13ff89..4f928901f3 100644
> --- a/crypt/crypt.h
> +++ b/crypt/crypt.h
> @@ -28,7 +28,10 @@
>   
>   __BEGIN_DECLS
>   
> -/* Encrypt at most 8 characters from KEY using salt to perturb DES.  */
> +/* Hash a password, KEY, for storage in /etc/shadow.  SALT selects the
> +   hashing algorithm to be used, and ensures that no two users' passwords
> +   are hashed to the same string.  The return value points to static
> +   storage which will be overwritten by the next call to crypt.  */
>   extern char *crypt (const char *__key, const char *__salt)
>        __THROW __nonnull ((1, 2));

Okay.

> diff --git a/elf/Makefile b/elf/Makefile
> index e658928305..ef9155dbd7 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -385,14 +385,21 @@ $(objpfx)tst-_dl_addr_inside_object: $(objpfx)dl-addr-obj.os
>   CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag)
>   endif
>   
> -# By default tst-linkall-static should try to use crypt routines to test
> -# static libcrypt use.
> +# We can only test static libcrypt use if libcrypt has been built,
> +# and either NSS crypto is not in use, or static NSS libraries are
> +# available.
> +ifeq ($(build-crypt),no)
> +CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
> +else
> +ifeq ($(nss-crypt),no)
> +CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
> +else
> +ifeq ($(static-nss-crypt),no)
> +CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
> +else
>   CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
> -# However, if we are using NSS crypto and we don't have a static
> -# library, then we exclude the use of crypt functions in the test.
> -# We similarly exclude libcrypt.a from the static link (see below).
> -ifeq (yesno,$(nss-crypt)$(static-nss-crypt))
> -CFLAGS-tst-linkall-static.c += -UUSE_CRYPT -DUSE_CRYPT=0
> +endif
> +endif
>   endif

Okay.

> @@ -1113,7 +1120,6 @@ localplt-built-dso := $(addprefix $(common-objpfx),\
>   				  rt/librt.so \
>   				  dlfcn/libdl.so \
>   				  resolv/libresolv.so \
> -				  crypt/libcrypt.so \
>   		       )
>   ifeq ($(build-mathvec),yes)
>   localplt-built-dso += $(addprefix $(common-objpfx), mathvec/libmvec.so)
> @@ -1121,6 +1127,9 @@ endif
>   ifeq ($(have-thread-library),yes)
>   localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library))
>   endif
> +ifeq ($(build-crypt),yes)
> +localplt-built-dso += $(addprefix $(common-objpfx), crypt/libcrypt.so)
> +endif

Okay.

> @@ -1395,6 +1404,7 @@ $(objpfx)tst-linkall-static: \
>     $(common-objpfx)resolv/libanl.a \
>     $(static-thread-library)
>   
> +ifeq ($(build-crypt),yes)
>   # If we are using NSS crypto and we have the ability to link statically
>   # then we include libcrypt.a, otherwise we leave out libcrypt.a and
>   # link as much as we can into the tst-linkall-static test.  This assumes
> @@ -1410,6 +1420,7 @@ ifeq (no,$(nss-crypt))
>   $(objpfx)tst-linkall-static: \
>     $(common-objpfx)crypt/libcrypt.a
>   endif
> +endif

Okay.

>   # The application depends on the DSO, and the DSO loads the plugin.
>   # The plugin also depends on the DSO. This creates the circular
> diff --git a/elf/tst-linkall-static.c b/elf/tst-linkall-static.c
> index e8df38f74e..d0f2592e67 100644
> --- a/elf/tst-linkall-static.c
> +++ b/elf/tst-linkall-static.c
> @@ -18,7 +18,9 @@
>   
>   #include <math.h>
>   #include <pthread.h>
> -#include <crypt.h>
> +#if USE_CRYPT
> +# include <crypt.h>
> +#endif
>   #include <resolv.h>
>   #include <dlfcn.h>
>   #include <utmp.h>

Okay.

> diff --git a/manual/install.texi b/manual/install.texi
> index 4bbbfcffa5..ce2d049f1a 100644
> --- a/manual/install.texi
> +++ b/manual/install.texi
> @@ -230,6 +230,18 @@ libnss_nisplus are not built at all.
>   Use this option to enable libnsl with all depending NSS modules and
>   header files.
>   
> +@item --disable-crypt
> +Do not install the password-hashing library @file{libcrypt} or the
> +header file @file{crypt.h}.  @file{unistd.h} will still declare the
> +function @code{crypt}, as required by POSIX.  Using this option does
> +not change the set of programs that may need to be linked with
> +@option{-lcrypt}; it only means that @theglibc{} will not provide that
> +library.

You need to use “POSIX@.” instead of “POSIX.” here.

> +This option is for hackers and distributions experimenting with
> +independently-maintained implementations of libcrypt.  It may become
> +the default in a future release.

Okay.

>   @item --disable-experimental-malloc
>   By default, a per-thread cache is enabled in @code{malloc}.  While
>   this cache can be disabled on a per-application basis using tunables
> diff --git a/posix/unistd.h b/posix/unistd.h
> index 5d4e07f6c8..fdf2d4b208 100644
> --- a/posix/unistd.h
> +++ b/posix/unistd.h
> @@ -1119,10 +1119,11 @@ extern int fdatasync (int __fildes);
>   #endif /* Use POSIX199309 */
>   
>   
> -/* XPG4.2 specifies that prototypes for the encryption functions must
> -   be defined here.  */
>   #ifdef	__USE_XOPEN
> -/* Encrypt at most 8 characters from KEY using salt to perturb DES.  */
> +/* Hash a password, KEY, for storage in /etc/shadow.  SALT selects the
> +   hashing algorithm to be used, and ensures that no two users' passwords
> +   are hashed to the same string.  The return value points to static
> +   storage which will be overwritten by the next call to crypt.  */
>   extern char *crypt (const char *__key, const char *__salt)
>        __THROW __nonnull ((1, 2));

Okay.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/4] New configure option --disable-crypt.
  2018-05-08 15:00   ` Florian Weimer
@ 2018-05-08 15:22     ` Zack Weinberg
  0 siblings, 0 replies; 19+ messages in thread
From: Zack Weinberg @ 2018-05-08 15:22 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Tue, May 8, 2018 at 11:00 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> +     header file 'crypt.h'.  'unistd.h' will still declare the function
>> +     'crypt', as required by POSIX. Using this option does not change
>> +     the set of programs that may need to be linked with '-lcrypt'; it
>> +     only means that the GNU C Library will not provide that library.
>
> Two spaces after dot; see below.
...
>> +Do not install the password-hashing library @file{libcrypt} or the
>> +header file @file{crypt.h}.  @file{unistd.h} will still declare the
>> +function @code{crypt}, as required by POSIX.  Using this option does
>> +not change the set of programs that may need to be linked with
>> +@option{-lcrypt}; it only means that @theglibc{} will not provide that
>> +library.
> You need to use “POSIX@.” instead of “POSIX.” here.

Will fix.  Thanks for the extra-careful proofreading.

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/4] Deprecate DES encryption functions.
  2018-05-08 14:33   ` Florian Weimer
@ 2018-05-08 15:24     ` Zack Weinberg
  0 siblings, 0 replies; 19+ messages in thread
From: Zack Weinberg @ 2018-05-08 15:24 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library, Carlos O'Donell, Rical Jasan

On Tue, May 8, 2018 at 10:33 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 05/06/2018 07:51 PM, Zack Weinberg wrote:
>
>> +* The functions 'encrypt', 'encrypt_r', 'setkey', 'setkey_r',
>> 'cbc_crypt',
>> +  'ecb_crypt', and 'des_setparity' are deprecated.  They encrypt and
>> decrypt
>> +  data with the DES block cipher, which is no longer considered secure.
>> +  Also, encrypt, encrypt_r, setkey, and setkey_r require awkward pre- and
>> +  post-processing of the encryption key and data to be encrypted, and
>> +  encrypt and setkey are not thread-safe.  Software that still uses these
>> +  functions should switch to a modern cryptography library, such as
>> GnuTLS.
>
> GNUTLS is no longer part of the GNU project.  You should recommend libgcrypt
> instead.

Thanks, I didn't know that.  Will change.  libgcrypt is also a better
suggestion because it's a cryptography library first, rather than a
TLS protocol client first.

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/4] Revise manual sections on cryptography and random numbers.
  2018-05-08 14:23   ` Florian Weimer
@ 2018-05-08 15:59     ` Zack Weinberg
  2018-05-08 17:51       ` Florian Weimer
  0 siblings, 1 reply; 19+ messages in thread
From: Zack Weinberg @ 2018-05-08 15:59 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Tue, May 8, 2018 at 10:23 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 05/06/2018 07:51 PM, Zack Weinberg wrote:
>> +Many countries have historically placed legal restrictions on the
>> +import, export, possession, or use of cryptographic tools.  These
>> +restrictions change frequently, so we cannot give you specific advice
>> +about what the situation might be in your country.  To the best of our
>> +knowledge, no one has objected to the export or import of @theglibc{}
>> +in many years,
>
> I think people routinely file notices for glibc with the appropriate
> authorities.  The whole thing doesn't really work the way the text implies.
> It's not that nobody complains, it's that all this work is done proactively.
> I don't think we need to get into detail here.
>
>> but if you are writing a program that performs
>> +cryptographic operations, we advise you to find out what your
>> +country's laws might be, first.  The one-way hash functions for
>> +password storage are less likely to be restricted than the DES-based
>> +encryption functions, because they cannot be used to send secret
>> +messages---the recipient would not be able to decrypt them.
>
> It's fairly easy to turn a one-way hash function into a stream cipher, so
> I'm not sure if the final sentence is correct.
>
> The HMAC construction can also be used with this and give you a cipher:
>
>   <https://people.csail.mit.edu/rivest/Chaffing.txt>
>
> I'm also not sure if DES qualifies as a cryptographic algorithm anymore, so
> the actual situation might well be the opposite of what you state. Sorry.

I will think about this some more, and possibly consult one of my
actual lawyer friends over at the EFF.  Do you have any thoughts on
more appropriate wording?  Or, do you think we should not discuss this
at all, which is how I had it in the previous revision?

>> +The function @code{crypt} converts a password string, @var{phrase},
>> +into a one-way hash suitable for storage in the user database.  The
>> +hash will consist entirely of printable ASCII characters.  It will not
>> +contain whitespace, nor any of the characters @kbd{:}, @kbd{;},
>> +@kbd{*}, @kbd{!}, or @kbd{\}.
>
> @code{':'} etc.?  These are bytes, not keyboard characters.

I always have problems deciding which of @samp/@code/@kbd/... to use
for this sort of thing.  The current Texinfo manual says specifically
to use @samp for single characters "unless @kbd or @key is more
appropriate", and I think you're right that it shouldn't be @kbd, so
I'll change them to @samp in the next revision.

>> +@tab @samp{$6$}
>
> Maybe use @code{"$6$"} etc. for the prefixes?  No strong preference on my
> part though.

In this case I think we need to use @samp, because the prefix for DES
is the empty string, which will come out as ‘’ with @samp but nothing
at all with @code.

> The code checks [that the salt uses only certain characters], right?  Or perhaps only for DES.

It looks like the code only checks for DES, but I think it's
appropriate to document that the salt should use only those characters
anyway.

>> +will begin with a @kbd{*} and will not be the same as @var{salt}.  In
> @code{'*'}?

@samp, again, I think.

>> -The @code{crypt_r} function does the same thing as @code{crypt}, but
>> -takes an extra parameter which includes space for its result (among
>> -other things), so it can be reentrant.  @code{data@w{->}initialized} must
>> be
>> -cleared to zero before the first time @code{crypt_r} is called.
>> -
>> -The @code{crypt_r} function is a GNU extension.
>> +The function @code{crypt_r} is a reentrant version of @code{crypt}.
>
> I don't think crypt_r is reentrant, it is merely thread-safe.  But no strong
> opinion.

The term 'reentrant' was used by the text this replaced (see above
quoted diff) but I think I will change it to 'thread-safe' here and
elsewhere.

>> +@samp{@w{memset(data, 0, sizeof data)}}
>
> Missing space before parentheses.

Will fix.

> Perhaps add a warning that struct crypt_data is very large and should not be
> allocated on the stack?

Yeah, good idea.

> Okay.  Maybe also say that these functions are not thread-safe?

Only encrypt and setkey are not thread-safe.  I will make sure this is
clear, though.

>> +The @code{setkey} function prepares to perform DES encryption or
>> +decryption using the key @var{key}.  @var{key} should point to an
>> +array of 64 @code{char}s, each of which must be set to either @samp{0}
>> +or @samp{1}; that is, each byte stores one bit of the key.  Every
>> +eighth byte (array indices 7, 15, 23, @dots{}) must be set to give it
>> +plus the preceding group of seven bytes odd parity.
>
> “must be set to the negation of the parity of the preceding seven
> bits/bytes”?

What I wrote is confusing, but I'm not sure this suggestion is correct
either.  I'll think about it some more.

>> +@samp{@w{memset(data, 0, sizeof data)}}
>
> Missing space before parenthesis.

Will fix.

>>     The function @code{ecb_crypt} encrypts or decrypts one or more blocks
>> -using DES.  Each block is encrypted independently.
>> +using DES.  Each block is encrypted independently, which means that if
>> +any two input blocks are the same, then their encryptions will also be
>> +the same.  This is an additional weakness in the encryption, on top of
>> +the weakness of DES itself.
>
> Maybe mention Electronic Codebook Mode (ECB)?

Good point, not everyone already knows what "ecb" means :)

>> +  if (getentropy (ubytes, sizeof ubytes))
>> +    {
>> +      perror ("getentropy");
>> +      return 1;
>> +    }
>
> Explicit check of getentropy return value against zero?  It's not exactly a
> boolean flag, after all.

getentropy is documented to return 0 on success or -1 on failure, so I
think 'if (getentropy (...))' is the way to go here.  If it returned
the number of bytes read, that would be a different story, but it's
getrandom that does that.

>> +  /* Retrieve the password for user argv[1]
>> +     from the user database.  */
>> +  pw = getpwnam (argv[1]);
>
> Check error?

Doh! Will fix.

>> -  ok = strcmp (result, pass) == 0;
>> +  ok = strcmp (result, pw->pw_passwd) == 0;
>
> Maybe add a comment that this could result in a timing oracle?

It doesn't, because we are comparing the hashes, not the raw
passwords.  Maybe I should say _that_?

>> +A @dfn{cryptographically strong pseudo-random number generator}
>> +(CSPRNG) is a PRNG that @emph{does} guarantee its output is
>> +unguessable.  Formally, there is no deterministic, polynomial-time
>> +algorithm@footnote{Assuming
>> +@iftex
>> +@c Don't typeset NP as if multiplying N by P. Use text italic for both.
>> +@math{\hbox{\it P} \neq \hbox{\it NP}}@c
>> +@end iftex
>> +@ifnottex
>> +@math{P ≠ NP}@c
>> +@end ifnottex
>> +.} that can tell the difference between the output of
>> +a CSPRNG and a sequence of numbers that really were chosen uniformly
>> +at random.  A CSPRNG still uses a seed and can only produce an
>> +astronomically small number of random sequences.
>
> I'm not sure if this detail is necessary.  If it is, you need to add
> “independent” somewhere.

I'm afraid I don't understand which bit of the above text is the
detail you think might not be necessary, or where the word
"independent" should appear.  This is probably because I have so
thoroughly internalized how the academic cryptography literature uses
the term "CSPRNG" that I no longer know how to explain it to someone
who's new to the topic. Could you clarify, please?

>> +Finally, a @dfn{true random number generator} (TRNG) produces random
>> +numbers not from a seed, but from some unpredictable physical process.
>> +In principle, a TRNG's output is unguessable, and is not limited to an
>> +astronomically small number of sequences.  However, TRNGs are very
>> +slow, and because there is no seed, there is no way to make one repeat
>> +its output.  Usually, it is best to use a TRNG only to choose the seed
>> +for a PRNG or CSPRNG.
>> +
>> +At present, @theglibc{} offers a variety of ordinary PRNGs, and on
>> +some operating systems it also offers access to an OS-provided TRNG.
>> +We may add a CSPRNG in the future.
>
> If this refers to arc4random, I don't think it's a CSPRNG under your
> definition.

Yes, that was the intent; why would it not qualify?

> And we shouldn't claim it has formal properties initially
> because that would make glibc subject to FIPS certification again, which is
> something we should avoid.

I meant to use "formal" in the mathematical sense -- "these are the
details of how the guarantee is made accessible to mathematical
proof".  Can you point me at some explanation of what phrasing might
or might not make a FIPS certification requirement apply?  I only know
the barest outline of that process.


>> +Some cryptographic applications need truly unpredictable bytes.
>> +@Theglibc{} provides two functions for this purpose, both of which
>> +access a true random generator implemented by the operating system.
>
> I don't think the Linux urandom generator qualifies as a TRNG, sorry.

Hmm.  I see why you say that, but for most programs' purposes it is
good enough.  Maybe that's what I should say, and also that if you
need something stronger you need to get yourself an actual piece of
hardware?

>
>> +Not all operating systems support these functions; programs that use
>> +them must be prepared for them to fail.  They are slow, and can only
>> +produce short sequences of unpredictable bytes.  Most programs should
>> +use these functions only to seed a cryptographically strong
>> +pseudo-random generator.
>
> The functions aren't *that* slow .  But I don't have a proposal for
> improving the wording.

I think maybe I just won't say they're slow.  The major reason for
wanting to use them only for seeds is the 256-byte limit on the output
of getentropy.

>>   This function is declared in @file{string.h}.
>>   @pindex string.h
>>   @@ -2487,9 +2485,7 @@ Note that @code{memfrob} a second time on the same
>> data structure
>>   returns it to its original state.
>>     This is a good function for hiding information from someone who
>> doesn't
>> -want to see it or doesn't want to see it very much.  To really prevent
>> -people from retrieving the information, use stronger encryption such as
>> -that described in @xref{Cryptographic Functions}.
>> +want to see it or doesn't want to see it very much.
>
> Hmm.  Okay I guess.

The point of this change is the manual shouldn't be endorsing DES even
by implication as a way of "really prevent[ing]" people from
retrieving information.  How about I mention libgcrypt again, instead
of saying nothing at all?

zw

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/4] Revise manual sections on cryptography and random numbers.
  2018-05-08 15:59     ` Zack Weinberg
@ 2018-05-08 17:51       ` Florian Weimer
  0 siblings, 0 replies; 19+ messages in thread
From: Florian Weimer @ 2018-05-08 17:51 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On 05/08/2018 05:58 PM, Zack Weinberg wrote:
> I will think about this some more, and possibly consult one of my
> actual lawyer friends over at the EFF.  Do you have any thoughts on
> more appropriate wording?  Or, do you think we should not discuss this
> at all, which is how I had it in the previous revision?

Not discussing it at all is fine with me.  I can't provide any concrete 
guidance for the current U.S. situation.

>>> +The function @code{crypt} converts a password string, @var{phrase},
>>> +into a one-way hash suitable for storage in the user database.  The
>>> +hash will consist entirely of printable ASCII characters.  It will not
>>> +contain whitespace, nor any of the characters @kbd{:}, @kbd{;},
>>> +@kbd{*}, @kbd{!}, or @kbd{\}.
>>
>> @code{':'} etc.?  These are bytes, not keyboard characters.
> 
> I always have problems deciding which of @samp/@code/@kbd/... to use
> for this sort of thing.  The current Texinfo manual says specifically
> to use @samp for single characters "unless @kbd or @key is more
> appropriate", and I think you're right that it shouldn't be @kbd, so
> I'll change them to @samp in the next revision.

I meant ':' as a C expression, hence wrapping it in @code.

>>> +@tab @samp{$6$}
>>
>> Maybe use @code{"$6$"} etc. for the prefixes?  No strong preference on my
>> part though.
> 
> In this case I think we need to use @samp, because the prefix for DES
> is the empty string, which will come out as ‘’ with @samp but nothing
> at all with @code.

Again, with "…" as a wrapper, so that the empty string is actually 
visible.  No strong opinion though.

>> The code checks [that the salt uses only certain characters], right?  Or perhaps only for DES.
> 
> It looks like the code only checks for DES, but I think it's
> appropriate to document that the salt should use only those characters
> anyway.

Right.

>>> +  if (getentropy (ubytes, sizeof ubytes))
>>> +    {
>>> +      perror ("getentropy");
>>> +      return 1;
>>> +    }
>>
>> Explicit check of getentropy return value against zero?  It's not exactly a
>> boolean flag, after all.
> 
> getentropy is documented to return 0 on success or -1 on failure, so I
> think 'if (getentropy (...))' is the way to go here.

Hmm.  I thought that the C/POSIX 0/-1 return value does not really 
qualify as a boolean because the meaning is reversed and the bit pattern 
is non-standard, but I'm not sure if that's part of our coding guidelines.

>>> -  ok = strcmp (result, pass) == 0;
>>> +  ok = strcmp (result, pw->pw_passwd) == 0;
>>
>> Maybe add a comment that this could result in a timing oracle?
> 
> It doesn't, because we are comparing the hashes, not the raw
> passwords.  Maybe I should say _that_?

It still makes me nervous. 8-/

In some cases, the comparison could go in the other direction.

>>> +A @dfn{cryptographically strong pseudo-random number generator}
>>> +(CSPRNG) is a PRNG that @emph{does} guarantee its output is
>>> +unguessable.  Formally, there is no deterministic, polynomial-time
>>> +algorithm@footnote{Assuming
>>> +@iftex
>>> +@c Don't typeset NP as if multiplying N by P. Use text italic for both.
>>> +@math{\hbox{\it P} \neq \hbox{\it NP}}@c
>>> +@end iftex
>>> +@ifnottex
>>> +@math{P ≠ NP}@c
>>> +@end ifnottex
>>> +.} that can tell the difference between the output of
>>> +a CSPRNG and a sequence of numbers that really were chosen uniformly
>>> +at random.  A CSPRNG still uses a seed and can only produce an
>>> +astronomically small number of random sequences.
>>
>> I'm not sure if this detail is necessary.  If it is, you need to add
>> “independent” somewhere.
> 
> I'm afraid I don't understand which bit of the above text is the
> detail you think might not be necessary, or where the word
> "independent" should appear.

The sequence of random variables against which the CSPRNG is compared 
must be uniformly distributed and independent, or something like that. 
This is something I last thought about probably fifteen years ago, so do 
not take my word for it.

However, I still think that this definition still has two problems: It 
is hard to prove anything in this area, so the definition isn't really 
helpful for documentation (because we don't know if our algorithm 
actually has that property).  And I'm vary of asymptomatics 
(“polynomial-time”) in this context anyway because our algorithms have 
fixed-size inputs and internal state, so everything is O(1) anyway.

>>> +Finally, a @dfn{true random number generator} (TRNG) produces random
>>> +numbers not from a seed, but from some unpredictable physical process.
>>> +In principle, a TRNG's output is unguessable, and is not limited to an
>>> +astronomically small number of sequences.  However, TRNGs are very
>>> +slow, and because there is no seed, there is no way to make one repeat
>>> +its output.  Usually, it is best to use a TRNG only to choose the seed
>>> +for a PRNG or CSPRNG.
>>> +
>>> +At present, @theglibc{} offers a variety of ordinary PRNGs, and on
>>> +some operating systems it also offers access to an OS-provided TRNG.
>>> +We may add a CSPRNG in the future.
>>
>> If this refers to arc4random, I don't think it's a CSPRNG under your
>> definition.
> 
> Yes, that was the intent; why would it not qualify?

We don't have proof for any NIST-approved algorithm that it is a CSPRNG, 
do we?

And existing proofs are often useless, see section 6 of 
<https://eprint.iacr.org/2006/229> (Neal Koblitz and Alfred Menezes, 
“Another Look at "Provable Security" II”).

>>> +Some cryptographic applications need truly unpredictable bytes.
>>> +@Theglibc{} provides two functions for this purpose, both of which
>>> +access a true random generator implemented by the operating system.
>>
>> I don't think the Linux urandom generator qualifies as a TRNG, sorry.
> 
> Hmm.  I see why you say that, but for most programs' purposes it is
> good enough.  Maybe that's what I should say, and also that if you
> need something stronger you need to get yourself an actual piece of
> hardware?

I think we should steer clear of crypto politics (including proof 
politics) and just say it's unpredictable.

> I think maybe I just won't say they're slow.  The major reason for
> wanting to use them only for seeds is the 256-byte limit on the output
> of getentropy.

That's a good point.

>>>    This function is declared in @file{string.h}.
>>>    @pindex string.h
>>>    @@ -2487,9 +2485,7 @@ Note that @code{memfrob} a second time on the same
>>> data structure
>>>    returns it to its original state.
>>>      This is a good function for hiding information from someone who
>>> doesn't
>>> -want to see it or doesn't want to see it very much.  To really prevent
>>> -people from retrieving the information, use stronger encryption such as
>>> -that described in @xref{Cryptographic Functions}.
>>> +want to see it or doesn't want to see it very much.
>>
>> Hmm.  Okay I guess.
> 
> The point of this change is the manual shouldn't be endorsing DES even
> by implication as a way of "really prevent[ing]" people from
> retrieving information.  How about I mention libgcrypt again, instead
> of saying nothing at all?

I like this idea.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt
  2018-05-06 17:52 [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Zack Weinberg
                   ` (3 preceding siblings ...)
  2018-05-06 17:52 ` [PATCH 1/4] Reorganize manual sections on cryptography and random numbers Zack Weinberg
@ 2018-05-08 22:56 ` Rical Jasan
  4 siblings, 0 replies; 19+ messages in thread
From: Rical Jasan @ 2018-05-08 22:56 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: libc-alpha, carlos, fweimer

On 05/06/2018 10:51 AM, Zack Weinberg wrote:
> I am not sure whether I remembered to address all of your other
> comments on the documentation changes, but I got the impression you
> wanted to re-review it from scratch anyway after the split-up?

Correct, thank you.  I'll be reviewing shortly.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/4] Reorganize manual sections on cryptography and random numbers.
  2018-05-06 17:52 ` [PATCH 1/4] Reorganize manual sections on cryptography and random numbers Zack Weinberg
  2018-05-08 13:29   ` Florian Weimer
@ 2018-05-09 11:36   ` Rical Jasan
  1 sibling, 0 replies; 19+ messages in thread
From: Rical Jasan @ 2018-05-09 11:36 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: libc-alpha, carlos, fweimer

On 05/06/2018 10:51 AM, Zack Weinberg wrote:
> In preparation for improvements to the discussion of cryptography,
> password handling, and random number generation, reorganize the
> sections of the manual that deal with these topics.  This patch
> neither deletes any old text nor introduces any new text; it only
> moves text around.  The description of 'getpass' moves to
> terminal.texi, since all it does is read a password from the
> controlling terminal with echo disabled.  The pseudo-random number
> generator sections from math.texi and the "Unpredictable Bytes"
> section of crypt.texi are moved to a new file random.texi.  Also, it
> is no longer true that crypt.texi's top @node needs to have no pointers.
> 
> 	* manual/crypt.texi: Move most of the introductory text to the
>         'crypt' section.  Move the example programs below the
>         @deftypefun for 'crypt_r'.  Move the DESERR_* table and
>         DES_FAILED deftypefun below cbc_crypt.  Move the entire
>         'getpass' section...
> 	* manual/terminal.texi: ...here.
> 
> 	* manual/random.texi: New file consolidating all discussion of
> 	random number generation.
> 	* manual/crypt.texi: 'Unpredictable Bytes' section moved to random.texi.
> 	* manual/math.texi: 'Pseudo-Random Numbers' section moved to
> 	random.texi.
> 	* manual/Makefile (chapters): Add 'random' after 'arith'.
> 	* manual/arith.texi, manual/time.texi: Update chapter-level node
> 	pointers.

This is a great high-level overview of a largely mechanical change.

Other than minor, necessary changes to keep the manual somewhat
cohesive, this appears to be a copy/paste to me (yes, I took the time).

Thank you,
Rical

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/4] Revise manual sections on cryptography and random numbers.
  2018-05-06 17:52 ` [PATCH 2/4] Revise manual sections on cryptography and random numbers Zack Weinberg
  2018-05-08 14:23   ` Florian Weimer
@ 2018-05-09 11:36   ` Rical Jasan
  2018-05-09 15:47     ` Joseph Myers
  1 sibling, 1 reply; 19+ messages in thread
From: Rical Jasan @ 2018-05-09 11:36 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: libc-alpha, carlos, fweimer

On 05/06/2018 10:51 AM, Zack Weinberg wrote:
> This is a major rewrite of the description of 'crypt'.  It also makes
> minor improvements to the description of the obsolete DES functions,
> and introduces some new introductory exposition to the "random number
> generation" chapter.
> 
> A few highlights of the content changes:
> 
>  - All references to FIPS have been removed.  The "Legal Problems"
>    section has also been removed, but I left a one-paragraph
>    cautionary note that there _are_, or have been, legal problems at
>    the top of the chapter.  I also removed the paragraph saying that
>    systems not connected to a network need no user authentication,
>    because that's a pretty rare situation nowadays.  (It still says
>    "sometimes it is necessary" to authenticate the user, though.)
> 
>  - I added documentation for all of the hash functions that glibc
>    actually supports, but not for the additional hash functions
>    supported by libxcrypt.  If we're going to keep this manual section
>    around after the transition is more advanced, it would probably
>    make sense to add them then.
> 
>  - There is much more detailed discussion of how to generate a salt,
>    and the failure behavior for crypt is documented.  (Returning an
>    invalid hash on failure is what libxcrypt does; Solar Designer's
>    notes say that this was done "for compatibility with old programs
>    that assume crypt can never fail".)
> 
>  - As far as I can tell, the header 'crypt.h' is entirely a GNU
>    invention, and never existed on any other Unix lineage.  The
>    functions 'crypt', 'encrypt', and 'setkey', however, were in Issue
>    1 of the SVID and are now in the XSI component of POSIX.  I tried
>    to make all of the @standards annotations consistent with this, but
>    I'm not sure I got them perfectly right.
> 
>  - The genpass.c example has been improved to use getentropy instead
>    of the current time to generate the salt.  It uses more random
>    bytes than is strictly necessary because I didn't want to
>    complicate the code with proper base64 encoding.
> 
>  - The testpass.c example has been improved to take a username as a
>    command-line argument and validate that user's password, instead of
>    hardwiring a hash.  It really ought to read passwords out of the
>    shadow file (getspnam() instead of getpwnam()), but we don't have
>    any documentation for the shadow file functions, and I don't want
>    to delay this work even more by writing some.
> 
>  - I tried to make the explanation of the encoding of the arguments to
>    'encrypt' and 'setkey' better.  It's still a bit confusing but I
>    don't think it's worth spending any more effort on.
> 
>  - I changed "hardware device" to "hardware DES accelerator" because a
>    hardware device could be anything.
> 
>  - DES_FAILED is a macro, not a function, and the description of the
>    value it returns was backwards.
> 
> 	* manual/crypt.texi (Cryptographic Functions): New initial
> 	exposition.
> 	(Legal Problems): Section removed, replaced by a short caution in
> 	the initial exposition for 'Cryptographic Functions'.
> 	(crypt): Section renamed to 'Password Storage'.  Full rewrite.
> 	(DES Encryption): Section renamed to 'Obsolete Encryption'.
> 	Remove all mention of FIPS.  State clearly that none of these
> 	functions should be used anymore.  Various other improvements to
> 	the text.
> 	* manual/examples/genpass.c: Generate a salt using getentropy
> 	instead of the current time.
> 	* manual/examples/testpass.c: Instead of a hard-coded password
> 	hash, demonstrate reading passwords from the user database.
> 	* manual/string.texi (strfry, memfrob): Remove cross-references to
> 	the obsolete DES encryption functions.
> 
> 	* manual/random.texi (Random Number Generation): New initial
> 	exposition.
> 	(Pseudo-Random Numbers): No need to xref the very next section.
> 	(Unpredictable Bytes): Improve initial exposition.  Clarify error
> 	behavior of getentropy and getrandom.
> ---

Another impeccable introduction, thank you.

>  manual/crypt.texi          | 445 ++++++++++++++++++++-----------------
>  manual/examples/genpass.c  |  38 ++--
>  manual/examples/testpass.c |  34 ++-
>  manual/random.texi         |  84 +++++--
>  manual/string.texi         |   6 +-
>  5 files changed, 358 insertions(+), 249 deletions(-)
> 
> diff --git a/manual/crypt.texi b/manual/crypt.texi
> index c24306c07c..a3c02be055 100644
> --- a/manual/crypt.texi
> +++ b/manual/crypt.texi
> @@ -2,73 +2,35 @@
>  @chapter Cryptographic Functions
>  @c %MENU% Password storage and obsolete encryption functions
>  
> -@vindex AUTH_DES
> -@cindex FIPS 140-2
> -It also provides support for Secure RPC, and some library functions that
> -can be used to perform normal DES encryption.  The @code{AUTH_DES}
> -authentication flavor in Secure RPC, as provided by @theglibc{},
> -uses DES and does not comply with FIPS 140-2 nor does any other use of DES
> -within @theglibc{}.  It is recommended that Secure RPC should not be used
> -for systems that need to comply with FIPS 140-2 since all flavors of
> -encrypted authentication use normal DES.
> +@Theglibc{} is not a general-purpose cryptography library, but it does
> +include one-way hash functions for password storage, and a set of
> +encryption functions based on the obsolete DES block cipher.  The
> +latter are present for historical reasons only, and should not be used
> +at all anymore; any existing programs that still use them need to be
> +updated to use ciphers that are still secure.

Could we say, "ciphers that are considered secure by modern standards"?
I know it's a bit of a mouthful, but "still" feels like DES originally
had a contemporary that has stood the test of time, or that glibc has
other ciphers that should be (or have been) used instead.  Maybe this is
a good moment to make yet another plug at using a cryptography library
for cryptography?  The introduction to Obsolete Encryption says "use one
of the many free encryption libraries that use modern ciphers", which
could work equally as well here too.

> +Many countries have historically placed legal restrictions on the
> +import, export, possession, or use of cryptographic tools.  These
> +restrictions change frequently, so we cannot give you specific advice
> +about what the situation might be in your country.  To the best of our
> +knowledge, no one has objected to the export or import of @theglibc{}
> +in many years, but if you are writing a program that performs
> +cryptographic operations, we advise you to find out what your
> +country's laws might be, first.  The one-way hash functions for
> +password storage are less likely to be restricted than the DES-based
> +encryption functions, because they cannot be used to send secret
> +messages---the recipient would not be able to decrypt them.

Noting Florian's comment in his reply, we could probably get rid of the
last sentence and keep the spirit of the paragraph intact.

>  
>  @menu
> -* Legal Problems::              This software can get you locked up, or worse.
> -* crypt::                       A one-way function for passwords.
> -* DES Encryption::              Routines for DES encryption.
> +* Password Storage::		A one-way function for passwords.
> +* Obsolete Encryption::		Routines for encrypting and decrypting
> +				  data using the obsolete DES block cipher.
>  @end menu
>  
> -@node Legal Problems
> -@section Legal Problems
> -
> -Because of the continuously changing state of the law, it's not possible
> -to provide a definitive survey of the laws affecting cryptography.
> -Instead, this section warns you of some of the known trouble spots; this
> -may help you when you try to find out what the laws of your country are.
> -
> -Some countries require that you have a license to use, possess, or import
> -cryptography.  These countries are believed to include Byelorussia,
> -Burma, India, Indonesia, Israel, Kazakhstan, Pakistan, Russia, and Saudi
> -Arabia.
> -
> -Some countries restrict the transmission of encrypted messages by radio;
> -some telecommunications carriers restrict the transmission of encrypted
> -messages over their network.
> -
> -Many countries have some form of export control for encryption software.
> -The Wassenaar Arrangement is a multilateral agreement between 33
> -countries (Argentina, Australia, Austria, Belgium, Bulgaria, Canada, the
> -Czech Republic, Denmark, Finland, France, Germany, Greece, Hungary,
> -Ireland, Italy, Japan, Luxembourg, the Netherlands, New Zealand, Norway,
> -Poland, Portugal, the Republic of Korea, Romania, the Russian
> -Federation, the Slovak Republic, Spain, Sweden, Switzerland, Turkey,
> -Ukraine, the United Kingdom and the United States) which restricts some
> -kinds of encryption exports.  Different countries apply the arrangement
> -in different ways; some do not allow the exception for certain kinds of
> -``public domain'' software (which would include this library), some
> -only restrict the export of software in tangible form, and others impose
> -significant additional restrictions.
> -
> -The United States has additional rules.  This software would generally
> -be exportable under 15 CFR 740.13(e), which permits exports of
> -``encryption source code'' which is ``publicly available'' and which is
> -``not subject to an express agreement for the payment of a licensing fee or
> -royalty for commercial production or sale of any product developed with
> -the source code'' to most countries.
> -
> -The rules in this area are continuously changing.  If you know of any
> -information in this manual that is out-of-date, please report it to
> -the bug database.  @xref{Reporting Bugs}.
> -
> -@node crypt
> -@section Encrypting Passwords
> -
> -On many systems, it is unnecessary to have any kind of user
> -authentication; for instance, a workstation which is not connected to a
> -network probably does not need any user authentication, because to use
> -the machine an intruder must have physical access.
> -
> -Sometimes, however, it is necessary to be sure that a user is authorized
> +@node Password Storage
> +@section Password Storage
> +
> +Sometimes it is necessary to be sure that a user is authorized
>  to use some service a machine provides---for instance, to log in as a
>  particular user id (@pxref{Users and Groups}).  One traditional way of
>  doing this is for each user to choose a secret @dfn{password}; then, the
> @@ -76,164 +38,224 @@ system can ask someone claiming to be a user what the user's password
>  is, and if the person gives the correct password then the system can
>  grant the appropriate privileges.
>  
> -If all the passwords are just stored in a file somewhere, then this file
> -has to be very carefully protected.  To avoid this, passwords are run
> -through a @dfn{one-way function}, a function which makes it difficult to
> -work out what its input was by looking at its output, before storing in
> -the file.
> -
> -@Theglibc{} provides a one-way function that is compatible with
> -the behavior of the @code{crypt} function introduced in FreeBSD 2.0.
> -It supports two one-way algorithms: one based on the MD5
> -message-digest algorithm that is compatible with modern BSD systems,
> -and the other based on the Data Encryption Standard (DES) that is
> -compatible with Unix systems.
> -
> -@deftypefun {char *} crypt (const char *@var{key}, const char *@var{salt})
> -@standards{BSD, crypt.h}
> -@standards{SVID, crypt.h}
> +Programs that handle passwords must take special care not to reveal
> +them to anyone, no matter what.  It is not enough to keep them in a
> +file that is only accessible with special privileges.  The file might
> +be ``leaked'' via a bug or misconfiguration, and system administrators
> +shouldn't learn everyone's password even if they have to edit that
> +file for some reason.  To avoid this, passwords should also be
> +converted into @dfn{one-way hashes}, using a @dfn{one-way function},
> +before they are stored.  It is believed that the only way to recover a
> +password from its one-way hash is to guess possible passwords, hash
> +them, and compare the output with the hashes stored in the password
> +file.  The one-way functions are designed to make this process
> +impractically slow, for all but the most obvious guesses.  (Do not use
> +a word from the dictionary as your password.)
> +
> +@Theglibc{} provides an interface to four different one-way functions,
> +based on the SHA-2-512, SHA-2-256, MD5, and DES cryptographic
> +primitives.  New passwords should be hashed with either of the
> +SHA-based functions.  The others are too weak for newly set passwords,
> +but we continue to support them for verifying old passwords.  The
> +DES-based hash is especially weak, because it ignores all but the
> +first eight characters of its input.
> +
> +@deftypefun {char *} crypt (const char *@var{phrase}, const char *@var{salt})

I suppose changing the variable name from KEY to PHRASE is more
accessible/intuitive to a wider audience, so OK, but it breaks
consistency with the other functions below.

> +@standards{X/Open, unistd.h}
> +@standards{GNU, crypt.h}

POSIX says crypt is in unistd.h (which is marked XSI) and has been
present from Issue 1, having been derived from Issue 1 of the SVID.  I
do not see a header include in the SYNOPSIS of crypt/encrypt/setkey in
my copy of the SVID 4Ev1, however, and I can't speak for BSD, so I'm not
sure if this is just /more correct/, or what.

It also touches on which standard we want to report (i.e., the first,
latest, all, etc.), and I think we may have been heading towards the
oldest relevant standard (which would probably be POSIX/XSI here; i.e.,
X/Open, if I'm understanding the interplay correctly).  Normally I would
suggest mentioning the origins in the text after changing the @standards
from BSD and SVID to X/Open, but since the POSIX docs point to the SVID,
I think there's enough of a trail left behind.

Perhaps someone else can weigh in on whether crypt.h is BSD or GNU.

>  @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
>  @c Besides the obvious problem of returning a pointer into static
>  @c storage, the DES initializer takes an internal lock with the usual
> -@c set of problems for AS- and AC-Safety.  The FIPS mode checker and the
> -@c NSS implementations of may leak file descriptors if canceled.  The
> +@c set of problems for AS- and AC-Safety.
> +@c The NSS implementations may leak file descriptors if cancelled.
>  @c The MD5, SHA256 and SHA512 implementations will malloc on long keys,
>  @c and NSS relies on dlopening, which brings about another can of worms.
>  
> -The @code{crypt} function takes a password, @var{key}, as a string, and
> -a @var{salt} character array which is described below, and returns a
> -printable ASCII string which starts with another salt.  It is believed
> -that, given the output of the function, the best way to find a @var{key}
> -that will produce that output is to guess values of @var{key} until the
> -original value of @var{key} is found.
> -
> -The @var{salt} parameter does two things.  Firstly, it selects which
> -algorithm is used, the MD5-based one or the DES-based one.  Secondly, it
> -makes life harder for someone trying to guess passwords against a file
> -containing many passwords; without a @var{salt}, an intruder can make a
> -guess, run @code{crypt} on it once, and compare the result with all the
> -passwords.  With a @var{salt}, the intruder must run @code{crypt} once
> -for each different salt.
> -
> -For the MD5-based algorithm, the @var{salt} should consist of the string
> -@code{$1$}, followed by up to 8 characters, terminated by either
> -another @code{$} or the end of the string.  The result of @code{crypt}
> -will be the @var{salt}, followed by a @code{$} if the salt didn't end
> -with one, followed by 22 characters from the alphabet
> -@code{./0-9A-Za-z}, up to 34 characters total.  Every character in the
> -@var{key} is significant.
> -
> -For the DES-based algorithm, the @var{salt} should consist of two
> -characters from the alphabet @code{./0-9A-Za-z}, and the result of
> -@code{crypt} will be those two characters followed by 11 more from the
> -same alphabet, 13 in total.  Only the first 8 characters in the
> -@var{key} are significant.
> -
> -The MD5-based algorithm has no limit on the useful length of the
> -password used, and is slightly more secure.  It is therefore preferred
> -over the DES-based algorithm.
> -
> -When the user enters their password for the first time, the @var{salt}
> -should be set to a new string which is reasonably random.  To verify a
> -password against the result of a previous call to @code{crypt}, pass
> -the result of the previous call as the @var{salt}.
> +The function @code{crypt} converts a password string, @var{phrase},
> +into a one-way hash suitable for storage in the user database.  The
> +hash will consist entirely of printable ASCII characters.  It will not
> +contain whitespace, nor any of the characters @kbd{:}, @kbd{;},
> +@kbd{*}, @kbd{!}, or @kbd{\}.
> +
> +The @var{salt} parameter controls which one-way function is used, and
> +it also ensures that the output of the one-way function is different
> +for every user, even if they have the same password.  This makes it
> +harder to guess passwords from a large user database.  Without salt,
> +the intruder could make a guess, run @code{crypt} on it once, and
> +compare the result with all the hashed passwords.  Salt forces the
> +intruder to make many calls to @code{crypt} for each guess.
> +
> +To verify a password, pass the previously hashed password as the
> +@var{salt}.  To hash a new password for storage, set @var{salt} to a
> +string consisting of a prefix plus a sequence of randomly chosen
> +characters, according to this table:
> +
> +@multitable @columnfractions .15 .1 .3
> +@headitem Algorithm @tab Prefix @tab Random sequence
> +@item SHA-2-512
> +@tab @samp{$6$}
> +@tab 16 characters
> +@item SHA-2-256
> +@tab @samp{$5$}
> +@tab 16 characters
> +@item MD5
> +@tab @samp{$1$}
> +@tab 8 characters
> +@item DES
> +@tab @samp{}
> +@tab 2 characters
> +@end multitable
> +
> +In all cases, the random characters should be chosen from the alphabet
> +@code{./0-9A-Za-z}.
> +
> +With all of the hash functions @emph{except} DES, @var{phrase} can be
> +arbitrarily long, and all eight bits of each byte are significant.
> +With DES, all but the first eight characters of @var{phrase} are ignored,
> +and the eighth bit of each byte is also ignored.
> +
> +@code{crypt} can fail.  Some implementations return @code{NULL} on
> +failure, and others return an @emph{invalid} hashed passphrase, which
> +will begin with a @kbd{*} and will not be the same as @var{salt}.  In
> +either case, @code{errno} will be set to indicate the problem.  Some
> +of the possible error codes are:
> +
> +@table @code
> +@item EINVAL
> +@var{salt} is invalid; neither a previously hashed password, nor a
> +well-formed new salt for any of the supported hash functions.
> +
> +@item EPERM
> +The hash function selected by @var{salt} has been disabled by local
> +policy.
> +
> +@item ENOMEM
> +Failed to allocate internal scratch storage.
> +
> +@item ENOSYS
> +@itemx EOPNOTSUPP
> +Hashing passphrases is not supported at all, or the hash function
> +selected by @var{salt} is not supported.  @Theglibc{} does not use
> +these error codes, but they may be encountered on other operating
> +systems.
> +@end table
> +
> +@code{crypt} uses static storage for both internal scratchwork and the
> +string it returns.  It is not safe to call @code{crypt} from multiple
> +threads simultaneously, and the string it returns will be overwritten
> +by any subsequent call to @code{crypt}.
> +
> +@code{crypt} is specified in the X/Open Portability Guide and is
> +present on nearly all historical Unix systems.  However, XPG does not

"the XPG"

> +specify any one-way functions.
> +
> +@code{crypt} is declared in @file{unistd.h}.  @Theglibc{} also
> +declares this function in @file{crypt.h}.
>  @end deftypefun
>  
> -@deftypefun {char *} crypt_r (const char *@var{key}, const char *@var{salt}, {struct crypt_data *} @var{data})
> +@deftypefun {char *} crypt_r (const char *@var{phrase}, const char *@var{salt}, {struct crypt_data *} @var{data})

I believe it's safe to strip the braces around the struct and remove the
intervening space between the pointer and variable, for formatting
consistency.  (The braces are important around the return type, at least
for generating the Summary, IIRC.)

>  @standards{GNU, crypt.h}
>  @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
>  @c Compared with crypt, this function fixes the @mtasurace:crypt
>  @c problem, but nothing else.
>  
> -The @code{crypt_r} function does the same thing as @code{crypt}, but
> -takes an extra parameter which includes space for its result (among
> -other things), so it can be reentrant.  @code{data@w{->}initialized} must be
> -cleared to zero before the first time @code{crypt_r} is called.
> -
> -The @code{crypt_r} function is a GNU extension.
> +The function @code{crypt_r} is a reentrant version of @code{crypt}.
> +Instead of static storage, it uses the memory pointed to by its
> +@var{data} argument for both scratchwork and the string it returns.
> +It can safely be used from multiple threads, as long as different
> +@var{data} objects are used in each thread.  The string it returns
> +will still be overwritten by another call with the same @var{data}.
> +@var{data} must be a pointer to a @samp{struct crypt_data} object

Shouldn't the @samp be @code?

> +allocated by the caller, and before one of these objects is used for
> +the first time, it must be erased using
> +@samp{@w{memset(data, 0, sizeof data)}}
> +or similar.

In the past, we've avoided using function calls inline within
paragraphs, so this should be, "erased using:

@smallexample
memset (data, 0, sizeof (data));
@end smallexample

@noident
or similar."

(Also note syntax/style differences in the C code.)

> +
> +@code{crypt_r} is a GNU extension.  It is declared in @file{crypt.h},
> +as is @samp{struct crypt_data}.

@code, again, I think.

>  @end deftypefun
>  
> -The @code{crypt} and @code{crypt_r} functions are prototyped in the
> -header @file{crypt.h}.
> -
> -The following short program is an example of how to use @code{crypt} the
> -first time a password is entered.  Note that the @var{salt} generation
> -is just barely acceptable; in particular, it is not unique between
> -machines, and in many applications it would not be acceptable to let an
> -attacker know what time the user's password was last set.
> +The following program shows how to use @code{crypt} the first time a
> +password is entered.  It uses @code{getentropy} to make the salt as
> +unpredictable as possible; @pxref{Unpredictable Bytes}.
>  
>  @smallexample
>  @include genpass.c.texi
>  @end smallexample
>  
> -The next program shows how to verify a password.  It prompts the user
> -for a password and prints ``Access granted.'' if the user types
> -@code{GNU libc manual}.
> +@c When we have documentation for getspnam, change the demo to use it.

As much as I hate doing things like this, if you're going to leave a
note-to-future-self, at least use a FIXME or TODO on the line, because
you know, someday, somebody's gonna grep 'em all and fix 'em.

Or just file a bug on the lack of documentation.  ;)

> +The next program shows how to verify a password stored in the system
> +user database in the traditional manner; @pxref{User Database}.  (On
> +newer installations, the passwords are instead stored in a ``shadow''
> +database that requires special privileges to access, and this program
> +will not work.)
>  
>  @smallexample
>  @include testpass.c.texi
>  @end smallexample
>  
> -@node DES Encryption
> -@section DES Encryption
> -
> -@cindex FIPS 46-3
> -The Data Encryption Standard is described in the US Government Federal
> -Information Processing Standards (FIPS) 46-3 published by the National
> -Institute of Standards and Technology.  The DES has been very thoroughly
> -analyzed since it was developed in the late 1970s, and no new
> -significant flaws have been found.
> -
> -However, the DES uses only a 56-bit key (plus 8 parity bits), and a
> -machine has been built in 1998 which can search through all possible
> -keys in about 6 days, which cost about US$200000; faster searches would
> -be possible with more money.  This makes simple DES insecure for most
> -purposes, and NIST no longer permits new US government systems
> -to use simple DES.
> -
> -For serious encryption functionality, it is recommended that one of the
> -many free encryption libraries be used instead of these routines.
> -
> -The DES is a reversible operation which takes a 64-bit block and a
> -64-bit key, and produces another 64-bit block.  Usually the bits are
> -numbered so that the most-significant bit, the first bit, of each block
> -is numbered 1.
> -
> -Under that numbering, every 8th bit of the key (the 8th, 16th, and so
> -on) is not used by the encryption algorithm itself.  But the key must
> -have odd parity; that is, out of bits 1 through 8, and 9 through 16, and
> -so on, there must be an odd number of `1' bits, and this completely
> -specifies the unused bits.
> +@node Obsolete Encryption
> +@section Obsolete Encryption

Some @cindices for "Data Encryption Standard" and "DES" would be great here.

> +
> +For historical reasons, @theglibc{} includes several functions which
> +perform encryption using the obsolete Data Encryption Standard (DES).
> +None of these functions should be used anymore.  Instead, use one of
> +the many free encryption libraries that use modern ciphers.
> +
> +DES is a block cipher standardized by the US government in 1977.  It
> +is no longer considered to be secure, and has been withdrawn as a
> +standard, because it only has @math{2@sup{56}} possible keys, so
> +testing all of them is practical.  In 1998, it cost US$250,000 to
> +build a massively parallel computer that could find the DES key that
> +encrypted a known message in three days.  In 2018, the same process
> +takes only one day, and there are online services that will do it for
> +less than US$100 per message.

This is a good update on the state of the art.

>  @deftypefun void setkey (const char *@var{key})
> -@standards{BSD, crypt.h}
> -@standards{SVID, crypt.h}
> +@standards{X/Open, stdlib.h}
> +@standards{GNU, crypt.h}

Same comments apply here as for crypt, above.

>  @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
>  @c The static buffer stores the key, making it fundamentally
>  @c thread-unsafe.  The locking issues are only in the initialization
>  @c path; cancelling the initialization will leave the lock held, it
>  @c would otherwise repeat the initialization on the next call.
>  
> -The @code{setkey} function sets an internal data structure to be an
> -expanded form of @var{key}.  @var{key} is specified as an array of 64
> -bits each stored in a @code{char}, the first bit is @code{key[0]} and
> -the 64th bit is @code{key[63]}.  The @var{key} should have the correct
> -parity.
> +The @code{setkey} function prepares to perform DES encryption or
> +decryption using the key @var{key}.  @var{key} should point to an
> +array of 64 @code{char}s, each of which must be set to either @samp{0}
> +or @samp{1}; that is, each byte stores one bit of the key.  Every
> +eighth byte (array indices 7, 15, 23, @dots{}) must be set to give it
> +plus the preceding group of seven bytes odd parity.  For instance, if

I feel this explanation is a vast improvement -- particularly given the
following explanation -- but I would inject some commas for grammar's
sake: "... it, plus the preceding group of seven bytes, odd parity."

I haven't vetted the source for correctness, but I think this paragraph
is much more understandable, overall, even going so far as to explain
parity without defining it...

> +there are three bytes set to @samp{1} among bytes 0 through 6, then
> +byte 7 must be set to @samp{0}, and similarly if there are four bytes
> +set to @samp{1} among bytes 8 through 14, then byte 15 must be set to
> +@samp{0}, and so on.  Thus, of the 64 bytes, only 56 can be used to

...although for odd parity, I believe the latter case should set the
parity bit/byte to 1.

As to the use of @samp for the 0's and 1's, I think they should be @math
(see [0]).

> +supply key data.
> +
> +The @code{setkey} function is specified in the X/Open Portability
> +Guide and is declared in @file{stdlib.h}.  @Theglibc{} also declares
> +this function in @file{crypt.h}.
>  @end deftypefun
>  
>  @deftypefun void encrypt (char *@var{block}, int @var{edflag})
> -@standards{BSD, crypt.h}
> -@standards{SVID, crypt.h}
> +@standards{X/Open, unistd.h}
> +@standards{GNU, crypt.h}

Same comments apply here as for crypt, above.

>  @safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
>  @c Same issues as setkey.
>  
> -The @code{encrypt} function encrypts @var{block} if
> -@var{edflag} is 0, otherwise it decrypts @var{block}, using a key
> -previously set by @code{setkey}.  The result is
> -placed in @var{block}.
> +The @code{encrypt} function encrypts @var{block} if @var{edflag} is 0,
> +otherwise it decrypts @var{block}, using a key previously set by
> +@code{setkey}.  The result overwrites the previous value of
> +@var{block}.
>  
> -Like @code{setkey}, @var{block} is specified as an array of 64 bits each
> -stored in a @code{char}, but there are no parity bits in @var{block}.
> +Like @code{setkey}, @var{block} is as an array of 64 @code{char}s,

"is an array"

> +each of which stores one bit of the block to be encrypted.  Unlike
> +@code{setkey}, there are no parity bits.  All 64 of the bits are
> +treated as data.

This is a good distinction.

> +The @code{encrypt} function is specified in the X/Open Portability
> +Guide and is declared in @file{unistd.h}.  @Theglibc{} also declares
> +this function in @file{crypt.h}.
>  @end deftypefun
>  
>  @deftypefun void setkey_r (const char *@var{key}, {struct crypt_data *} @var{data})

We could strip the braces from the struct and collapse the space here as
well.  This isn't necessarily everywhere we could do this, which could
even be a patch in and of itself---I'm only pointing it out because it
showed up in the diff.

> @@ -245,25 +267,30 @@ stored in a @code{char}, but there are no parity bits in @var{block}.
>  These are reentrant versions of @code{setkey} and @code{encrypt}.  The
>  only difference is the extra parameter, which stores the expanded
>  version of @var{key}.  Before calling @code{setkey_r} the first time,
> -@code{data->initialized} must be cleared to zero.
> -@end deftypefun
> +@code{data} must be erased using
> +@samp{@w{memset(data, 0, sizeof data)}}
> +or similar.

An @smallexample would avoid the paragraph-inline function here, as above.

> -The @code{setkey_r} and @code{encrypt_r} functions are GNU extensions.
> -@code{setkey}, @code{encrypt}, @code{setkey_r}, and @code{encrypt_r} are
> -defined in @file{crypt.h}.
> +@code{setkey_r} and @code{encrypt_r} are GNU extensions.  They are
> +declared in @file{crypt.h}.
> +@end deftypefun
>  
>  @deftypefun int ecb_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode})
>  @standards{SUNRPC, rpc/des_crypt.h}
>  @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>  
>  The function @code{ecb_crypt} encrypts or decrypts one or more blocks
> -using DES.  Each block is encrypted independently.

Normally, we would write this in such a way that ECB was spelled out
beforehand, but it's viable to work in parenthetically here.

> +using DES.  Each block is encrypted independently, which means that if
> +any two input blocks are the same, then their encryptions will also be
> +the same.  This is an additional weakness in the encryption, on top of
> +the weakness of DES itself.
>  
>  The @var{blocks} and the @var{key} are stored packed in 8-bit bytes, so
>  that the first bit of the key is the most-significant bit of
>  @code{key[0]} and the 63rd bit of the key is stored as the
> -least-significant bit of @code{key[7]}.  The @var{key} should have the
> -correct parity.
> +least-significant bit of @code{key[7]}.  The least-significant bit of
> +each byte must be chosen to give each byte odd parity, as with
> +@code{setkey}.

OK.

>  @var{len} is the number of bytes in @var{blocks}.  It should be a
>  multiple of 8 (so that there are a whole number of blocks to encrypt).
> @@ -271,33 +298,33 @@ multiple of 8 (so that there are a whole number of blocks to encrypt).
>  
>  The result of the encryption replaces the input in @var{blocks}.
>  
> -The @var{mode} parameter is the bitwise OR of two of the following:
> +The @var{mode} parameter should be the bitwise OR of one of these two
> +constants:
>  
>  @vtable @code
>  @item DES_ENCRYPT
>  @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, specifies that
>  @var{blocks} is to be encrypted.
>  
>  @item DES_DECRYPT
>  @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, specifies that
>  @var{blocks} is to be decrypted.
> +@end vtable

OK, but is there a default?

> +@noindent
> +with one of these two constants:
>  
> +@vtable @code
>  @item DES_HW
>  @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, asks to use a hardware
> -device.  If no hardware device is available, encryption happens anyway,
> -but in software.
> +Use a hardware DES accelerator, if available.  If no accelerator is
> +available, encryption or decryption will still occur, but in software.
>  
>  @item DES_SW
>  @standards{SUNRPC, rpc/des_crypt.h}
> -This constant, used in the @var{mode} parameter, specifies that no
> -hardware device is to be used.
> +Do not use a hardware DES accelerator.
>  @end vtable
>  
> -@end deftypefun
> -
>  @deftypefun int cbc_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode}, char *@var{ivec})

I think the indentation breaks here (i.e., the "@end deftypefun"
shouldn't have been removed).

>  @standards{SUNRPC, rpc/des_crypt.h}
>  @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> @@ -324,7 +351,8 @@ bytes.
>  Otherwise, all the parameters are similar to those for @code{ecb_crypt}.
>  @end deftypefun
>  
> -The result of the function will be one of these values:

We should reindent back here, after the function descriptions.

> +@code{ecb_crypt} and @code{cbc_crypt} both return one of the following
> +values:
>  
>  @vtable @code
>  @item DESERR_NONE
> @@ -333,7 +361,7 @@ The encryption succeeded.
>  
>  @item DESERR_NOHWDEVICE
>  @standards{SUNRPC, rpc/des_crypt.h}
> -The encryption succeeded, but there was no hardware device available.
> +The encryption succeeded, but there was no hardware accelerator available.
>  
>  @item DESERR_HWERROR
>  @standards{SUNRPC, rpc/des_crypt.h}
> @@ -344,13 +372,20 @@ The encryption failed because of a hardware problem.
>  The encryption failed because of a bad parameter, for instance @var{len}
>  is not a multiple of 8 or @var{len} is larger than @code{DES_MAXDATA}.
>  @end vtable
> +@end deftypefun
> +
> +For convenience, there is a macro which distinguishes successful from
> +failure result codes:
>  
> -@deftypefun int DES_FAILED (int @var{err})
> +@deftypefn Macro int DES_FAILED (int @var{err})

OK (Function-like macro).

>  @standards{SUNRPC, rpc/des_crypt.h}
>  @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> -This macro returns 1 if @var{err} is a `success' result code from
> -@code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
> -@end deftypefun
> +This macro returns a nonzero value if @var{err} is a failure result
> +code from @code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
> +@end deftypefn

Good.

> +There is also a helper function which assists in producing well-formed
> +DES keys:
>  
>  @deftypefun void des_setparity (char *@var{key})
>  @standards{SUNRPC, rpc/des_crypt.h}


> diff --git a/manual/examples/genpass.c b/manual/examples/genpass.c
...> diff --git a/manual/examples/testpass.c b/manual/examples/testpass.c
...> diff --git a/manual/random.texi b/manual/random.texi

I have to pass on these for now due to time constraints, but I think
I've thrown in a few cents worth.

Thank you,
Rical

[0] https://sourceware.org/ml/libc-alpha/2017-11/msg00653.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/4] Revise manual sections on cryptography and random numbers.
  2018-05-09 11:36   ` Rical Jasan
@ 2018-05-09 15:47     ` Joseph Myers
  0 siblings, 0 replies; 19+ messages in thread
From: Joseph Myers @ 2018-05-09 15:47 UTC (permalink / raw)
  To: Rical Jasan; +Cc: Zack Weinberg, libc-alpha, carlos, fweimer

On Wed, 9 May 2018, Rical Jasan wrote:

> Perhaps someone else can weigh in on whether crypt.h is BSD or GNU.

crypt.h is not in the CSRG BSD history (so not in BSD 4.4, which is what 
would typically have been meant by BSD in the manual).  See e.g. 
<https://github.com/weiss/original-bsd>.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2018-05-09 15:47 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-06 17:52 [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Zack Weinberg
2018-05-06 17:51 ` [PATCH 3/4] Deprecate DES encryption functions Zack Weinberg
2018-05-08 14:33   ` Florian Weimer
2018-05-08 15:24     ` Zack Weinberg
2018-05-06 17:52 ` [PATCH 2/4] Revise manual sections on cryptography and random numbers Zack Weinberg
2018-05-08 14:23   ` Florian Weimer
2018-05-08 15:59     ` Zack Weinberg
2018-05-08 17:51       ` Florian Weimer
2018-05-09 11:36   ` Rical Jasan
2018-05-09 15:47     ` Joseph Myers
2018-05-06 17:52 ` [PATCH 4/4] New configure option --disable-crypt Zack Weinberg
2018-05-08 15:00   ` Florian Weimer
2018-05-08 15:22     ` Zack Weinberg
2018-05-06 17:52 ` [PATCH 1/4] Reorganize manual sections on cryptography and random numbers Zack Weinberg
2018-05-08 13:29   ` Florian Weimer
2018-05-08 13:37     ` Zack Weinberg
2018-05-08 13:38       ` Florian Weimer
2018-05-09 11:36   ` Rical Jasan
2018-05-08 22:56 ` [PATCH 0/4 v3] Revise crypto documentation, deprecate DES, add --disable-crypt Rical Jasan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).