summaryrefslogtreecommitdiffstats
path: root/lib/libcrypt
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2014-05-11 14:54:17 +0000
committerdes <des@FreeBSD.org>2014-05-11 14:54:17 +0000
commitb6c03d4ad70a056fb956f7ab6f41ffbbc8e01aa7 (patch)
treec4db2520074fc1a4c684ce9904525e4126c9b987 /lib/libcrypt
parent971a9ff5f33ccfe7bfeaaf8348af0ff4b8ae3c6e (diff)
downloadFreeBSD-src-b6c03d4ad70a056fb956f7ab6f41ffbbc8e01aa7.zip
FreeBSD-src-b6c03d4ad70a056fb956f7ab6f41ffbbc8e01aa7.tar.gz
MFH (r261913): switch default to sha512
MFH (r264964): rewrite so DES still works when not the default MFH (r262945): clean up man page
Diffstat (limited to 'lib/libcrypt')
-rw-r--r--lib/libcrypt/crypt.366
-rw-r--r--lib/libcrypt/crypt.c133
2 files changed, 91 insertions, 108 deletions
diff --git a/lib/libcrypt/crypt.3 b/lib/libcrypt/crypt.3
index f14a6eb..50829c2 100644
--- a/lib/libcrypt/crypt.3
+++ b/lib/libcrypt/crypt.3
@@ -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 consisting of an underscore followed
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 using
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
diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c
index bfcbb20..040fdc1 100644
--- a/lib/libcrypt/crypt.c
+++ b/lib/libcrypt/crypt.c
@@ -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));
}
OpenPOWER on IntegriCloud