[v2] New configure option --disable-crypt.

Message ID 20180418183411.4828-1-zackw@panix.com
State Superseded
Headers

Commit Message

Zack Weinberg April 18, 2018, 6:34 p.m. UTC
  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
and encrypt, and stdlib.h continues to declare setkey.  However,
encrypt, setkey, encrypt_r, and setkey_r are marked
__attribute_deprecated__ in all of the places where they are declared.
These functions perform encryption and decryption with single DES,
which is no longer considered secure; the separately maintained
implementation of libcrypt doesn't declare them at all or allow
new programs to link with them (it does provide them as compat
symbols).

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

On x86_64-linux, installed stripped libraries are unchanged by this patch,
and installed stripped libraries other than libcrypt are unchanged by
this patch + specifying --disable-crypt at configure time.

zw

	* 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).

	* crypt/Makefile: Remove code conditional on $(crypt-in-libc),
	which is never set.
	(CFLAGS-cert.c): Add -Wno-deprecated-declarations.
	* 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, encrypt, and
	setkey.	 Mark encrypt, setkey, encrypt_r, and setkey_r with
	__attribute_deprecated__.
	* posix/unistd.h: Update comments above crypt and encrypt.
	Mark encrypt with __attribute_deprecated__.
	* stdlib/stdlib.h: Update comments above setkey.
	Mark setkey with __attribute_deprecated__.
---
 Makeconfig               |  9 +++++++--
 NEWS                     | 22 +++++++++++++++++++++-
 config.make.in           |  1 +
 configure                | 32 +++++++++++++++++++++++++++++++-
 configure.ac             | 11 +++++++++++
 conform/Makefile         | 11 +++++++----
 crypt/Makefile           |  5 ++---
 crypt/crypt.h            | 22 +++++++++++++++-------
 elf/Makefile             | 27 +++++++++++++++++++--------
 elf/tst-linkall-static.c |  4 +++-
 posix/unistd.h           | 15 +++++++++------
 stdlib/stdlib.h          |  9 +++++++--
 12 files changed, 133 insertions(+), 35 deletions(-)
  

Comments

Andreas Schwab April 18, 2018, 8:41 p.m. UTC | #1
On Apr 18 2018, Zack Weinberg <zackw@panix.com> wrote:

> diff --git a/NEWS b/NEWS
> index 92c9b14220..b530124dae 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -31,7 +31,7 @@ Deprecated and removed features, and other changes affecting compatibility:
>     installed.  Software that was using either header should be updated to
>     use standard <stdio.h> interfaces instead.
>  
> - * The stdio.h functions 'getc' and 'putc' are no longer defined as macros.
> + * The stdio functions 'getc' and 'putc' are no longer defined as macros.
>     This was never required by the C standard, and the macros just expanded
>     to call alternative names for the same functions.  If you hoped getc and
>     putc would provide performance improvements over fgetc and fputc, instead

This is unrelated.

Andreas.
  
Rical Jasan April 18, 2018, 9:05 p.m. UTC | #2
It looks like --runstatedir slipped in to the generated configure.  I'm
not opposed to it in general, and I don't think it's used anywhere
anyway, but it doesn't seem related, and isn't mentioned.  I think it's
an artifact of autotools versions.

I believe --disable-crypt should also be added to install.texi (and
INSTALL regenerated, IIRC).

There is also an entire chapter in the manual devoted to these
functions.  It does convey, "Don't do this," to an extent -- in a number
of ways -- but I'm open to suggestions for improvement, particularly in
light of this patch.  It's a pretty short chapter.

Rical
  
Zack Weinberg April 23, 2018, 3:22 p.m. UTC | #3
On Wed, Apr 18, 2018 at 5:05 PM, Rical Jasan <rj@2c3t.io> wrote:
> It looks like --runstatedir slipped in to the generated configure.  I'm
> not opposed to it in general, and I don't think it's used anywhere
> anyway, but it doesn't seem related, and isn't mentioned.  I think it's
> an artifact of autotools versions.

Yeah, it is.  I have Debian's autoconf 2.69, which has --runstatedir
backported from autoconf trunk.  I can hand-edit that back out if
people think it's worth avoiding the churn.

> I believe --disable-crypt should also be added to install.texi (and
> INSTALL regenerated, IIRC).

Will fix.

> There is also an entire chapter in the manual devoted to these
> functions.  It does convey, "Don't do this," to an extent -- in a number
> of ways -- but I'm open to suggestions for improvement, particularly in
> light of this patch.  It's a pretty short chapter.

Yeah, I'm just looking over that chapter now.

zw
  
Zack Weinberg April 23, 2018, 3:29 p.m. UTC | #4
On Wed, Apr 18, 2018 at 4:41 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> On Apr 18 2018, Zack Weinberg <zackw@panix.com> wrote:
>
>> diff --git a/NEWS b/NEWS
>> index 92c9b14220..b530124dae 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -31,7 +31,7 @@ Deprecated and removed features, and other changes affecting compatibility:
>>     installed.  Software that was using either header should be updated to
>>     use standard <stdio.h> interfaces instead.
>>
>> - * The stdio.h functions 'getc' and 'putc' are no longer defined as macros.
>> + * The stdio functions 'getc' and 'putc' are no longer defined as macros.
>>     This was never required by the C standard, and the macros just expanded
>>     to call alternative names for the same functions.  If you hoped getc and
>>     putc would provide performance improvements over fgetc and fputc, instead
>
> This is unrelated.

I split this and pushed it separately.

zw
  

Patch

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 92c9b14220..b530124dae 100644
--- a/NEWS
+++ b/NEWS
@@ -31,7 +31,7 @@  Deprecated and removed features, and other changes affecting compatibility:
    installed.  Software that was using either header should be updated to
    use standard <stdio.h> interfaces instead.
 
- * The stdio.h functions 'getc' and 'putc' are no longer defined as macros.
+ * The stdio functions 'getc' and 'putc' are no longer defined as macros.
    This was never required by the C standard, and the macros just expanded
    to call alternative names for the same functions.  If you hoped getc and
    putc would provide performance improvements over fgetc and fputc, instead
@@ -57,6 +57,26 @@  Deprecated and removed features, and other changes affecting compatibility:
    these macros should first include <sys/types.h>, and then include
    <sys/sysmacros.h> if __GNU_LIBRARY__ is defined.
 
+ * The functions 'encrypt', 'encrypt_r', 'setkey', and 'setkey_r' are
+   deprecated.  They encrypt and decrypt short "blocks" of data with the
+   DES block cipher, which is no longer considered secure; also, they
+   require awkward pre- and post-processing of the 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.
+
+ * We have tentative plans to deprecate glibc's implementation of the
+   password-hashing functions 'crypt' and 'crypt_r'.  We will continue
+   to declare crypt in <unistd.h>, as required by POSIX, and programs
+   that use crypt or crypt_r should not need to change at all.  However,
+   the header file <crypt.h> and library libcrypt.{a,so} will come from
+   a separate development project that will, we hope, keep up better with
+   new password-hashing algorithms.
+
+   In this release, if the configure option --disable-crypt is used,
+   glibc will not install <crypt.h> or libcrypt.  The plan is to make
+   this the default behavior in a future release.
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/config.make.in b/config.make.in
index 9e5e24b2c6..d9891b2cd8 100644
--- a/config.make.in
+++ b/config.make.in
@@ -96,6 +96,7 @@  cross-compiling = @cross_compiling@
 force-install = @force_install@
 link-obsolete-rpc = @link_obsolete_rpc@
 build-obsolete-nsl = @build_obsolete_nsl@
+build-crypt = @build_crypt@
 build-nscd = @build_nscd@
 use-nscd = @use_nscd@
 build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
diff --git a/configure b/configure
index 7a8bd3f817..eea206fdf0 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
@@ -730,6 +731,7 @@  infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -779,6 +781,7 @@  enable_all_warnings
 enable_werror
 enable_multi_arch
 enable_experimental_malloc
+enable_crypt
 enable_nss_crypt
 enable_obsolete_rpc
 enable_obsolete_nsl
@@ -840,6 +843,7 @@  datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1092,6 +1096,15 @@  do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1229,7 +1242,7 @@  fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1382,6 +1395,7 @@  Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1448,6 +1462,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 +3521,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 +3537,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 303800df73..1e2f21bf52 100644
--- a/crypt/Makefile
+++ b/crypt/Makefile
@@ -32,9 +32,8 @@  libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
 
 tests := cert md5c-test sha256c-test sha512c-test badsalttest
 
-ifeq ($(crypt-in-libc),yes)
-routines += $(libcrypt-routines)
-endif
+# cert.c tests the deprecated setkey/encrypt interface
+CFLAGS-cert.c = -Wno-deprecated-declarations
 
 ifeq ($(nss-crypt),yes)
 nss-cpp-flags := -DUSE_NSS \
diff --git a/crypt/crypt.h b/crypt/crypt.h
index 5da098b715..4f928901f3 100644
--- a/crypt/crypt.h
+++ b/crypt/crypt.h
@@ -28,17 +28,25 @@ 
 
 __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));
 
-/* 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 +71,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/elf/Makefile b/elf/Makefile
index e658928305..ef9155dbd7 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -385,14 +385,21 @@  $(objpfx)tst-_dl_addr_inside_object: $(objpfx)dl-addr-obj.os
 CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag)
 endif
 
-# By default tst-linkall-static should try to use crypt routines to test
-# static libcrypt use.
+# We can only test static libcrypt use if libcrypt has been built,
+# and either NSS crypto is not in use, or static NSS libraries are
+# available.
+ifeq ($(build-crypt),no)
+CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
+else
+ifeq ($(nss-crypt),no)
+CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
+else
+ifeq ($(static-nss-crypt),no)
+CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
+else
 CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
-# However, if we are using NSS crypto and we don't have a static
-# library, then we exclude the use of crypt functions in the test.
-# We similarly exclude libcrypt.a from the static link (see below).
-ifeq (yesno,$(nss-crypt)$(static-nss-crypt))
-CFLAGS-tst-linkall-static.c += -UUSE_CRYPT -DUSE_CRYPT=0
+endif
+endif
 endif
 
 include ../Rules
@@ -1113,7 +1120,6 @@  localplt-built-dso := $(addprefix $(common-objpfx),\
 				  rt/librt.so \
 				  dlfcn/libdl.so \
 				  resolv/libresolv.so \
-				  crypt/libcrypt.so \
 		       )
 ifeq ($(build-mathvec),yes)
 localplt-built-dso += $(addprefix $(common-objpfx), mathvec/libmvec.so)
@@ -1121,6 +1127,9 @@  endif
 ifeq ($(have-thread-library),yes)
 localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library))
 endif
+ifeq ($(build-crypt),yes)
+localplt-built-dso += $(addprefix $(common-objpfx), crypt/libcrypt.so)
+endif
 
 vpath localplt.data $(+sysdep_dirs)
 
@@ -1395,6 +1404,7 @@  $(objpfx)tst-linkall-static: \
   $(common-objpfx)resolv/libanl.a \
   $(static-thread-library)
 
+ifeq ($(build-crypt),yes)
 # If we are using NSS crypto and we have the ability to link statically
 # then we include libcrypt.a, otherwise we leave out libcrypt.a and
 # link as much as we can into the tst-linkall-static test.  This assumes
@@ -1410,6 +1420,7 @@  ifeq (no,$(nss-crypt))
 $(objpfx)tst-linkall-static: \
   $(common-objpfx)crypt/libcrypt.a
 endif
+endif
 
 # The application depends on the DSO, and the DSO loads the plugin.
 # The plugin also depends on the DSO. This creates the circular
diff --git a/elf/tst-linkall-static.c b/elf/tst-linkall-static.c
index e8df38f74e..d0f2592e67 100644
--- a/elf/tst-linkall-static.c
+++ b/elf/tst-linkall-static.c
@@ -18,7 +18,9 @@ 
 
 #include <math.h>
 #include <pthread.h>
-#include <crypt.h>
+#if USE_CRYPT
+# include <crypt.h>
+#endif
 #include <resolv.h>
 #include <dlfcn.h>
 #include <utmp.h>
diff --git a/posix/unistd.h b/posix/unistd.h
index 4d149f9945..fdf2d4b208 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -1119,18 +1119,21 @@  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));
 
 /* 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