Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 11 May 2014 14:54:18 +0000 (UTC)
From:      Dag-Erling Smørgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r265879 - stable/10/lib/libcrypt
Message-ID:  <201405111454.s4BEsImq019330@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: des
Date: Sun May 11 14:54:17 2014
New Revision: 265879
URL: http://svnweb.freebsd.org/changeset/base/265879

Log:
  MFH (r261913): switch default to sha512
  MFH (r264964): rewrite so DES still works when not the default
  MFH (r262945): clean up man page

Modified:
  stable/10/lib/libcrypt/crypt.3
  stable/10/lib/libcrypt/crypt.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libcrypt/crypt.3
==============================================================================
--- stable/10/lib/libcrypt/crypt.3	Sun May 11 13:48:21 2014	(r265878)
+++ stable/10/lib/libcrypt/crypt.3	Sun May 11 14:54:17 2014	(r265879)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 9, 2011
+.Dd March 9, 2014
 .Dt CRYPT 3
 .Os
 .Sh NAME
@@ -63,11 +63,16 @@ Currently these include the
 .Tn MD5
 hash,
 .Tn NT-Hash
-(compatible with Microsoft's NT scheme)
+.Pq compatible with Microsoft's NT scheme
 and
 .Tn Blowfish .
-The algorithm used will depend upon the format of the Salt (following
-the Modular Crypt Format (MCF)), if
+The algorithm used will depend upon the format of the Salt
+.Po
+following
+the Modular Crypt Format
+.Pq MCF
+.Pc ,
+if
 .Tn DES
 and/or
 .Tn Blowfish
@@ -77,8 +82,10 @@ has been called to change the default.
 .Pp
 The first argument to
 .Nm
-is the data to hash (usually a password), in a
-.Dv null Ns -terminated
+is the data to hash
+.Pq usually a password ,
+in a
+.Dv NUL Ns -terminated
 string.
 The second is the salt, in one of three forms:
 .Pp
@@ -96,22 +103,19 @@ If it begins with the string
 then the Modular Crypt Format is used, as outlined below.
 .It Traditional
 If neither of the above is true, it assumes the Traditional Format,
-using the entire string as the salt (or the first portion).
+using the entire string as the salt
+.Pq or the first portion .
 .El
 .Pp
 All routines are designed to be time-consuming.
-A brief test on a
-.Tn Pentium
-166/MMX shows the
-.Tn DES
-crypt to do approximately 2640 crypts
-a CPU second and MD5 to do about 62 crypts a CPU second.
 .Ss DES Extended Format:
 The
 .Ar key
-is divided into groups of 8 characters (the last group is null-padded)
-and the low-order 7 bits of each character (56 bits per group) are
-used to form the
+is divided into groups of 8 characters
+.Pq the last group is NUL-padded
+and the low-order 7 bits of each character
+.Pq 56 bits per group
+are used to form the
 .Tn DES
 key as follows:
 the first group of 56 bits becomes the initial
@@ -127,7 +131,8 @@ The salt is a 9-character array consisti
 by 4 bytes of iteration count and 4 bytes of salt.
 These are encoded as printable characters, 6 bits per character,
 least significant character first.
-The values 0 to 63 are encoded as ``./0-9A-Za-z''.
+The values 0 to 63 are encoded as
+.Dq ./0-9A-Za-z .
 This allows 24 bits for both
 .Fa count
 and
@@ -138,7 +143,8 @@ The
 introduces disorder in the
 .Tn DES
 algorithm in one of 16777216 or 4096 possible ways
-(i.e., with 24 or 12 bits: if bit
+.Po
+i.e., with 24 or 12 bits: if bit
 .Em i
 of the
 .Ar salt
@@ -148,7 +154,8 @@ and
 .Em i+24
 are swapped in the
 .Tn DES
-E-box output).
+E-box output
+.Pc .
 .Pp
 The
 .Tn DES
@@ -157,11 +164,13 @@ key is used to encrypt a 64-bit constant
 iterations of
 .Tn DES .
 The value returned is a
-.Dv null Ns -terminated
-string, 20 or 13 bytes (plus null) in length, consisting of the
+.Dv NUL Ns -terminated
+string, 20 or 13 bytes
+.Pq plus NUL
+in length, consisting of the
 .Ar salt
 followed by the encoded 64-bit encryption.
-.Ss "Modular" crypt:
+.Ss Modular crypt:
 If the salt begins with the string
 .Fa $digit$
 then the Modular Crypt Format is used.
@@ -170,11 +179,10 @@ The
 represents which algorithm is used in encryption.
 Following the token is
 the actual salt to use in the encryption.
-The length of the salt is limited
-to 8 characters--because the length of the returned output is also limited
-(_PASSWORD_LEN).
-The salt must be terminated with the end of the string
-(NULL) or a dollar sign.
+The maximum length of the salt used depends upon the module.
+The salt must be terminated with the end of the string character
+.Pq NUL
+or a dollar sign.
 Any characters after the dollar sign are ignored.
 .Pp
 Currently supported algorithms are:
@@ -199,7 +207,7 @@ An example salt would be:
 .Bl -tag -width 6n -offset indent
 .It Cm "$4$thesalt$rest"
 .El
-.Ss "Traditional" crypt:
+.Ss Traditional crypt:
 The algorithm used will depend upon whether
 .Fn crypt_set_format
 has been called and whether a global default format has been specified.
@@ -216,7 +224,7 @@ if it is available, or MD5 if not.
 .Pp
 How the salt is used will depend upon the algorithm for the hash.
 For
-best results, specify at least two characters of salt.
+best results, specify at least eight characters of salt.
 .Pp
 The
 .Fn crypt_get_format

Modified: stable/10/lib/libcrypt/crypt.c
==============================================================================
--- stable/10/lib/libcrypt/crypt.c	Sun May 11 13:48:21 2014	(r265878)
+++ stable/10/lib/libcrypt/crypt.c	Sun May 11 14:54:17 2014	(r265879)
@@ -1,6 +1,7 @@
-/*
- * Copyright (c) 1999
- *      Mark Murray.  All rights reserved.
+/*-
+ * Copyright (c) 1999 Mark Murray
+ * Copyright (c) 2014 Dag-Erling Smørgrav
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,114 +29,88 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
-#include <string.h>
+
 #include <libutil.h>
+#include <string.h>
 #include <unistd.h>
+
 #include "crypt.h"
 
-static const struct {
+/*
+ * List of supported crypt(3) formats.  The first element in the list will
+ * be the default.
+ */
+static const struct crypt_format {
 	const char *const name;
 	char *(*const func)(const char *, const char *);
 	const char *const magic;
-} crypt_types[] = {
-#ifdef HAS_DES
-	{
-		"des",
-		crypt_des,
-		NULL
-	},
-#endif
-	{
-		"md5",
-		crypt_md5,
-		"$1$"
-	},
+} crypt_formats[] = {
+	/* default format */
+	{ "sha512",	crypt_sha512,		"$6$"	},
+
+	/* other supported formats */
+	{ "md5",	crypt_md5,		"$1$"	},
 #ifdef HAS_BLOWFISH
-	{
-		"blf",
-		crypt_blowfish,
-		"$2"
-	},
+	{ "blf",	crypt_blowfish,		"$2"	},
 #endif
-	{
-		"nth",
-		crypt_nthash,
-		"$3$"
-	},
-	{
-		"sha256",
-		crypt_sha256,
-		"$5$"
-	},
-	{
-		"sha512",
-		crypt_sha512,
-		"$6$"
-	},
-	{
-		NULL,
-		NULL,
-		NULL
-	}
-};
-
+	{ "nth",	crypt_nthash,		"$3$"	},
+	{ "sha256",	crypt_sha256,		"$5$"	},
 #ifdef HAS_DES
-#define CRYPT_DEFAULT	"des"
-#else
-#define CRYPT_DEFAULT	"md5"
+	{ "des",	crypt_des,		"_"	},
 #endif
 
-static int crypt_type = -1;
+	/* sentinel */
+	{ NULL,		NULL,			NULL	}
+};
 
-static void
-crypt_setdefault(void)
-{
-	size_t i;
+static const struct crypt_format *crypt_format = &crypt_formats[0];
 
-	if (crypt_type != -1)
-		return;
-	for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
-		if (strcmp(CRYPT_DEFAULT, crypt_types[i].name) == 0) {
-			crypt_type = (int)i;
-			return;
-		}
-	}
-	crypt_type = 0;
-}
+#define DES_SALT_ALPHABET \
+	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
 
+/*
+ * Returns the name of the currently selected format.
+ */
 const char *
 crypt_get_format(void)
 {
 
-	crypt_setdefault();
-	return (crypt_types[crypt_type].name);
+	return (crypt_format->name);
 }
 
+/*
+ * Selects the format to use for subsequent crypt(3) invocations.
+ */
 int
-crypt_set_format(const char *type)
+crypt_set_format(const char *format)
 {
-	size_t i;
+	const struct crypt_format *cf;
 
-	crypt_setdefault();
-	for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
-		if (strcmp(type, crypt_types[i].name) == 0) {
-			crypt_type = (int)i;
+	for (cf = crypt_formats; cf->name != NULL; ++cf) {
+		if (strcasecmp(cf->name, format) == 0) {
+			crypt_format = cf;
 			return (1);
 		}
 	}
 	return (0);
 }
 
+/*
+ * Hash the given password with the given salt.  If the salt begins with a
+ * magic string (e.g. "$6$" for sha512), the corresponding format is used;
+ * otherwise, the currently selected format is used.
+ */
 char *
 crypt(const char *passwd, const char *salt)
 {
-	size_t i;
+	const struct crypt_format *cf;
 
-	crypt_setdefault();
-	for (i = 0; i < sizeof(crypt_types) / sizeof(crypt_types[0]) - 1; i++) {
-		if (crypt_types[i].magic != NULL && strncmp(salt,
-		    crypt_types[i].magic, strlen(crypt_types[i].magic)) == 0)
-			return (crypt_types[i].func(passwd, salt));
-	}
-	return (crypt_types[crypt_type].func(passwd, salt));
+	for (cf = crypt_formats; cf->name != NULL; ++cf)
+		if (cf->magic != NULL && strstr(salt, cf->magic) == salt)
+			return (cf->func(passwd, salt));
+#ifdef HAS_DES
+	if (strlen(salt) == 13 && strspn(salt, DES_SALT_ALPHABET) == 13)
+		return (crypt_des(passwd, salt));
+#endif
+	return (crypt_format->func(passwd, salt));
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405111454.s4BEsImq019330>