This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 2/4] Revise manual sections on cryptography and random numbers.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]