[Bug 192431] New: Crypt(3) (-lcrypt) does not work as documented

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Wed Aug 6 12:36:02 UTC 2014


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=192431

            Bug ID: 192431
           Summary: Crypt(3) (-lcrypt) does not work as documented
           Product: Base System
           Version: 9.3-RELEASE
          Hardware: Any
                OS: Any
            Status: Needs Triage
          Severity: Affects Many People
          Priority: ---
         Component: bin
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: papowell at astart.com

This has been reported as 189958 broken /usr/bin/crypt but this has a much more
serisous impact than is incidated that bug report and the accompanying
comments.
For that reason, I am submitting a new bug report.

On FreeBSD 9.3 Release, the crypt(3) function does not behave as
documented and also not as on FreeBSD 8.4.  The documented and
expected default is tu generate the legacy DES encryption but this
has been changed.  The crypt() function is used directly by Perl
and PHP and affects these as well.

The crypt(3) C library routine is used by Perl/PHP.  This change 
has broken a large number of other things.  While there is no
argument about the 'strength' of the hash/encryption,  the documentation
states that it will behave in a specific manner,  and as far as I
can tell with a quick scan of the FreeBSD archives, there has been
no discussion of the impact of making this change.

I am surprised that one of the core functions behavior (crypt) was 
modified and this was not put into the FreeBSD 9.3 release notes.

I would strongly suggest that you publicize this and send out 
instructions on how to a) make the 'des' encryption the default b)
recompile everything that uses crypt and is statically linked c)
warn Perl and PHP users about this impact so they can update their
Perl and PHP.  (Note, I might be wrong about PHP, but I checked
Perl and it uses the -lcrypt library).

Details:

NAME
     crypt -- Trapdoor encryption
LIBRARY
     Crypt Library (libcrypt, -lcrypt)
SYNOPSIS
     #include <unistd.h> char * crypt(const char *key, const char
     *salt); const char * crypt_get_format(void); int
     crypt_set_format(const char *string);

DESCRIPTION
     The crypt() function performs password hashing with additional
     code added to deter key search attempts.  Different algorithms
     can be used to in the hash.  Currently these include the NBS
     Data Encryption Standard (DES), MD5 hash, NT-Hash (compatible
     with Microsoft's NT scheme) and Blowfish.  The algorithm used
     will depend upon the format of the Salt (following the Modular
     Crypt Format (MCF)), if DES and/or Blowfish is installed or
     not, and whether crypt_set_format() has been called to change
     the default.

     The first argument to crypt is the data to hash (usually a
     password), in a NUL-terminated string.  The second is the salt,
     in one of three forms:       Extended     If it begins with an underscore
(``_'')
       then the DES
            Extended Format is used in interpreting
            both the key and the salt, as outlined
            below.
       Modular      If it begins with the string ``$digit$''
       then the Mod-
            ular Crypt Format is used, as outlined
            below.
       Traditional  If neither of the above is true, it assumes
       the Tradi-
            tional Format, using the entire string as
            the salt (or the first portion).

 ...

   Traditional crypt:
     The algorithm used will depend upon whether crypt_set_format()
     has been called and whether a global default format has been
     specified.  Unless a global default has been specified or
     crypt_set_format() has set the for- mat to something else, the
     built-in default format is used.  This is cur- rently DES if
     it is available, or MD5 if not.

     The crypt_get_format() function returns a constant string that
     represents the name of the algorithm currently used.  Valid
     values are `des', `blf', `md5', `sha256', `sha512' and `nth'.

     The crypt_set_format() function sets the default encoding
     format accord- ing to the supplied string.

Test Program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main( int argc, char **argv, char **envp )
{
    const char *password = "testpassword";
    const char *salt = "_testpassword";
    const char *format = crypt_get_format();
    const char *output = crypt(password,password);
    fprintf( stdout, "Password '%s', format '%s', output '%s'\n", password,
format, output );
    output = crypt(password,salt);
    fprintf( stdout, "Password '%s', salt '%s', output '%s'\n", password, salt,
output );

    int status = crypt_set_format("des");
    format = crypt_get_format();
    output = crypt(password,password);
    fprintf( stdout, "status %d, Password '%s', format '%s', output '%s'\n",
      status, password, format, output );
    output = crypt(password,salt);
    fprintf( stdout, "Password '%s', salt '%s', output '%s'\n", password, salt,
output );
    exit( 0 );
}FreeBSD 9.3:
Pssword 'testpassword', format 'sha512', output
'$6$testpassword$QvM4M3dhSAaiMa6EthlRMq3g8efvl1GySUxAyuXAIN.
DmgGZuDLqKqi.wZ/PzWadf7YYxAKVlXmjq9ajS1R7y0'
Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA'
status 1, Password 'testpassword', format 'des', output 'tek4edTZE898g'
Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA'
assword 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA'


FreeBSD 8.4:
Password 'testpassword', format 'des', output 'tek4edTZE898g'
Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA'
status 1, Password 'testpassword', format 'des', output 'tek4edTZE898g'
Password 'testpassword', salt '_testpassword', output '_testpass6q8PHhqkDCA'

>From the FreeBSD 8.4 source:
/usr/src/lib/libcrypt/crypt.c:

        static const struct {
            const char *const name;
            char *(*const func)(const char *, const char *);
            const char *const magic;
        } crypt_types[] = {
        #ifdef HAS_DES
            {
                "des",
                crypt_des,
                NULL            {
                "md5",
                crypt_md5,
                "$1$"
            },

>From the FreeBSD 9.3 source.  Note that the default format
is set to sha512, not des:

        /*
         * 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_formats[] = {
            /* default format */
            { "sha512", crypt_sha512,       "$6$"   },

            /* other supported formats */
            { "md5",    crypt_md5,      "$1$"   },
        #ifdef HAS_BLOWFISH
            { "blf",    crypt_blowfish,     "$2"    },
        #endif
            { "nth",    crypt_nthash,       "$3$"   },
            { "sha256", crypt_sha256,       "$5$"   },
        #ifdef HAS_DES
            { "des",    crypt_des,      "_" },
        #endif

            },
        #endif



            /* sentinel */
            { NULL,     NULL,           NULL    }
        };


Suggestion:

        static const struct crypt_format {
            const char *const name;
            char *(*const func)(const char *, const char *);
            const char *const magic;
        } crypt_formats[] = {
            /* default format */
        #ifdef HAS_DES
            { "des",    crypt_des,      "_" },
        #endif
            { "sha512", crypt_sha512,       "$6$"   },

            /* other supported formats */
            { "md5",    crypt_md5,      "$1$"   },
        #ifdef HAS_BLOWFISH
            { "blf",    crypt_blowfish,     "$2"    },
        #endif
            { "nth",    crypt_nthash,       "$3$"   },
            { "sha256", crypt_sha256,       "$5$"   },

            /* sentinel */
            { NULL,     NULL,           NULL    }
        };

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list