From patchwork Sun May 6 17:51:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Weinberg X-Patchwork-Id: 909350 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-92079-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=panix.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="Bevwu/bh"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40fCyR65Bmz9s27 for ; Mon, 7 May 2018 03:52:47 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; q=dns; s= default; b=ATMyUt1w36bbvrIYN1B5nAHyGVkrpL3z/+xsL2n1oKI2Um3BfMYvn t1gx88SWbUR0wusitrZJp4xDOHm4i+a5HkoMsXt61/Mrqm+CpkOVHm7oJMXlDlEy azvpgRhEMuBi6NEEZHP0PHLdJ4MuZm4pwkXo61VT3RQ0HlZ3AtD1ZY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; s=default; bh=S2MevhWWnuJcXGDZBiFQ2k7Cbhg=; b=Bevwu/bh+XzPxDauYfBP0aVsEP9y FG2ySL0WwJyJ2Wc4AJU7iVYhISXQKmquF/TPOx+i8jA+rlpCy208J7eYSWdCiHw1 fVKmQ08Z2qq5Z4BtYHTYRoNoOv8rMM66p7LxR29I0w+XivacMHckB2E44jKIWoUe 06vT6vcpVephNM8= Received: (qmail 82198 invoked by alias); 6 May 2018 17:52:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 82083 invoked by uid 89); 6 May 2018 17:52:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.5 required=5.0 tests=BAYES_05, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS, TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=demands, arrives, obtaining, passwords X-HELO: mailbackend.panix.com From: Zack Weinberg To: libc-alpha@sourceware.org Cc: carlos@redhat.com, fweimer@redhat.com, rj@2c3t.io Subject: [PATCH 1/4] Reorganize manual sections on cryptography and random numbers. Date: Sun, 6 May 2018 13:51:50 -0400 Message-Id: <20180506175153.22629-2-zackw@panix.com> In-Reply-To: <20180506175153.22629-1-zackw@panix.com> References: <20180506175153.22629-1-zackw@panix.com> MIME-Version: 1.0 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 From patchwork Sun May 6 17:51:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Zack Weinberg X-Patchwork-Id: 909347 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-92076-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=panix.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="Y9E39oEY"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40fCxp6gDdz9s2t for ; Mon, 7 May 2018 03:52:14 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; q=dns; s=default; b=vQDtfzptDLXfDZ5cIG4Nz+U66fMpI3EL3roLR8KQWp8 l71cVQeMecnWEYrsjpgofj8l4M+ULwRVbWTI2nDOLNsgji8VOqx94uvTJivvy0/F XZaSO5cO1S6ZD5T/d+tshQ6KifEY4UXY0qkR4dGqrmqlFiKm5LayCK8DrZUCMSwE = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; s=default; bh=lwqdn8B6nBy7CSFBt3Z3UAoMCRg=; b=Y9E39oEYYpsqcl4WZ nLwE3c9Y4pxcfmu+/QoMEErA1VraojxbVdUkOznJkFx5bd3o2DXzaHtbDjqzZMN9 tkK83zhgpROskT/WmzKwJfyqhFFA+LqGVjIG3MACCkmqx+7ZSn+otTgC0aQSZxbN 89pM+5owpsP8A8LCokzL6rAHY8= Received: (qmail 81586 invoked by alias); 6 May 2018 17:52:03 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 81439 invoked by uid 89); 6 May 2018 17:52:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-21.0 required=5.0 tests=AWL, BAYES_50, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ADVERT2, KAM_SHORT, LOTS_OF_MONEY, SPF_PASS autolearn=ham version=3.3.2 spammy=Republic, korea, Korea, Turkey X-HELO: mailbackend.panix.com From: Zack Weinberg To: libc-alpha@sourceware.org Cc: carlos@redhat.com, fweimer@redhat.com, rj@2c3t.io Subject: [PATCH 2/4] Revise manual sections on cryptography and random numbers. Date: Sun, 6 May 2018 13:51:51 -0400 Message-Id: <20180506175153.22629-3-zackw@panix.com> In-Reply-To: <20180506175153.22629-1-zackw@panix.com> References: <20180506175153.22629-1-zackw@panix.com> MIME-Version: 1.0 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 -#include #include #include 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 . */ +#include +#include #include #include #include #include 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{}. From patchwork Sun May 6 17:51:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Weinberg X-Patchwork-Id: 909346 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-92075-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=panix.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="pnmFJ7Yp"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40fCxd4gWTz9s27 for ; Mon, 7 May 2018 03:52:05 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; q=dns; s= default; b=dz4Ve11qQmzOeA83Y6Uno1f6r2N9uoYQM0QvlSSnUeiGb0bll3jXi VvKqb3HeucBi4760lf6/rZteI/deiHQ0tI9zdQGZlq40iXgc+7/c9jVa1sZuSoPx Jy0GZdDKjJXpU3HOdMSVem0JUvz0wvTgfiESpcRVVYpdQMClyPeKxY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; s=default; bh=KT0qfpt6K26GOUK3KU/EjDwivtI=; b=pnmFJ7YpsU/s9rF4dXjJhFUDQhug wIOq0B3vd9IRy92XgEJDeZ2WU1d4ddNJ7hOJcnHjBak3EqP3xwutv5bbaJwm6wAv yZUeBU2cyMi4egbEPoBUMTT4jrs21ZjkJBNN7ehu5tB/7jMX0LoByxXLQf3X1GMV XZqIKtWnWBw3JeA= Received: (qmail 81002 invoked by alias); 6 May 2018 17:51:58 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 80993 invoked by uid 89); 6 May 2018 17:51:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=book, Secure, odd, DES X-HELO: mailbackend.panix.com From: Zack Weinberg To: libc-alpha@sourceware.org Cc: carlos@redhat.com, fweimer@redhat.com, rj@2c3t.io Subject: [PATCH 3/4] Deprecate DES encryption functions. Date: Sun, 6 May 2018 13:51:52 -0400 Message-Id: <20180506175153.22629-4-zackw@panix.com> In-Reply-To: <20180506175153.22629-1-zackw@panix.com> References: <20180506175153.22629-1-zackw@panix.com> MIME-Version: 1.0 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 and 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 From patchwork Sun May 6 17:51:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Weinberg X-Patchwork-Id: 909349 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-92078-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=panix.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="fGrY2F/m"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40fCy94D3Bz9s27 for ; Mon, 7 May 2018 03:52:33 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; q=dns; s= default; b=jHIgy57jG5bwgsme1uXcLYPOMnfdnZrYwYklNo8mxiiti6TQd3yWP a2sKrLW+6KF4Fu3WjE94iDxRZuZ7zyQVpPmLtBOJmPcm7oSrFtqB3rhU84syxL2D OcoYbvybG5XS1I4zBIX7+kQRzk7Y3gPceLIEmjAwJLSWeiXnAFMnCc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; s=default; bh=AqdGedYed22fUcAJnQJW85m7EAM=; b=fGrY2F/m5p+5jBD7o1p6TvZkXfKN FQv/GjD+X1YF4bZGwwov/wFhMIZqz/1YSxeImNb4XCBSFXiBtMv9BzFjYFom4ORv NQJvFbDL84UfF6bRLatdAWCDfJ295SHRgPwFzugcSb+Q6cEJF+kHETNTWYNoa2S+ dI1NrRP6LsIIJxI= Received: (qmail 81995 invoked by alias); 6 May 2018 17:52:06 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 81591 invoked by uid 89); 6 May 2018 17:52:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=passwords, basis, tentative, affecting X-HELO: l2mail1.panix.com From: Zack Weinberg To: libc-alpha@sourceware.org Cc: carlos@redhat.com, fweimer@redhat.com, rj@2c3t.io Subject: [PATCH 4/4] New configure option --disable-crypt. Date: Sun, 6 May 2018 13:51:53 -0400 Message-Id: <20180506175153.22629-5-zackw@panix.com> In-Reply-To: <20180506175153.22629-1-zackw@panix.com> References: <20180506175153.22629-1-zackw@panix.com> MIME-Version: 1.0 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 , as required by POSIX, and programs + that use crypt or crypt_r should not need to change at all. However, + the header file 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 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 #include -#include +#if USE_CRYPT +# include +#endif #include #include #include 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));