From: Nolan Lum Date: Wed, 1 Dec 2010 21:49:53 +0000 (-0500) Subject: Add sha256/512 support to libcrypt, change default X-Git-Tag: v2.10.0~526 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/6737f3b945f8531f8d5934dfaad3b4bb4a48b739 Add sha256/512 support to libcrypt, change default * Add sha256 and sha512 support to libcrypt. * Change the default password hash to sha256. * All old passwords will of course still works, but all new ones will be created using sha256. Sponsored-by: Google Code-In --- diff --git a/etc/login.conf b/etc/login.conf index 794c733..2310e98 100644 --- a/etc/login.conf +++ b/etc/login.conf @@ -19,7 +19,7 @@ # Note that entries like "cputime" set both "cputime-cur" and "cputime-max" default:\ - :passwd_format=md5:\ + :passwd_format=sha256:\ :copyright=/etc/COPYRIGHT:\ :welcome=/etc/motd:\ :setenv=MAIL=/var/mail/$,BLOCKSIZE=K,FTP_PASSIVE_MODE=YES:\ diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile index 9e590a0..20c2599 100644 --- a/lib/libcrypt/Makefile +++ b/lib/libcrypt/Makefile @@ -7,7 +7,8 @@ SHLIB_MAJOR= 3 LIB= crypt .PATH: ${.CURDIR}/../libmd -SRCS= crypt.c crypt-md5.c md5c.c misc.c +SRCS= crypt.c crypt-md5.c crypt-sha256.c crypt-sha512.c \ + md5c.c sha256c.c sha512c.c misc.c WARNS?= 2 MAN= crypt.3 MLINKS= crypt.3 crypt_get_format.3 crypt.3 crypt_set_format.3 @@ -24,7 +25,9 @@ CFLAGS+= -I${.CURDIR} -DHAS_DES -DHAS_BLOWFISH .PATH: ${.CURDIR}/../libutil SRCS+= auth.c property.c .for sym in MD5Init MD5Final MD5Update MD5Pad auth_getval \ - property_find properties_read properties_free + property_find properties_read properties_free \ + SHA256_Init SHA256_Update SHA256_Final \ + SHA512_Init SHA512_Update SHA512_Final CFLAGS+= -D${sym}=__${sym} .endfor PRECIOUSLIB= yes diff --git a/lib/libcrypt/crypt-sha256.c b/lib/libcrypt/crypt-sha256.c new file mode 100644 index 0000000..ce50c57 --- /dev/null +++ b/lib/libcrypt/crypt-sha256.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2010 + * The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Nolan Lum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "crypt.h" + +/* + * New password crypt. + */ + +char* +crypt_sha256(const char *pw, const char *salt) +{ + static const char *magic = "$3$"; /* Magic string for this + * algorithm. Easier to change + * when factored as constant. + */ + static char passwd[120], *p; + static const char *sp, *ep; + unsigned char final[SHA256_SIZE]; + int sl; + SHA256_CTX ctx; + unsigned long l; + + /* Refine the salt. */ + sp = salt; + + /* If it starts with the magic string, then skip that. */ + if (!strncmp(sp, magic, strlen(magic))) + sp += strlen(magic); + + /* Stop at the first '$', max 8 chars. */ + for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) + continue; + + /* Get the actual salt length. */ + sl = ep - sp; + + SHA256_Init(&ctx); + + /* Hash in the password first. */ + SHA256_Update(&ctx, pw, strlen(pw)); + + /* Then the magic string */ + SHA256_Update(&ctx, magic, sizeof(magic)); + + /* Then the raw salt. */ + SHA256_Update(&ctx, sp, sl); + + /* Finish and create the output string. */ + SHA256_Final(final, &ctx); + strcpy(passwd, magic); + strncat(passwd, sp, sl); + strcat(passwd, "$"); + + p = passwd + strlen(passwd); + + l = (final[ 0] << 16) | (final[11] << 8) | final[21]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 1] << 16) | (final[12] << 8) | final[22]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 2] << 16) | (final[13] << 8) | final[23]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 3] << 16) | (final[14] << 8) | final[24]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 4] << 16) | (final[15] << 8) | final[25]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 5] << 16) | (final[16] << 8) | final[26]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 6] << 16) | (final[17] << 8) | final[27]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 7] << 16) | (final[18] << 8) | final[28]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 8] << 16) | (final[19] << 8) | final[29]; + _crypt_to64(p, l, 4); p += 4; + l = (final[ 9] << 16) | (final[20] << 8) | final[30]; + _crypt_to64(p, l, 4); p += 4; + l = (final[10] << 16) | (final[31] << 8); + _crypt_to64(p, l, 4); p += 4; + *p = '\0'; + + /* Clear memory. */ + memset(final, 0, sizeof(final)); + + return (passwd); +} diff --git a/lib/libcrypt/crypt-sha512.c b/lib/libcrypt/crypt-sha512.c new file mode 100644 index 0000000..6b58a28 --- /dev/null +++ b/lib/libcrypt/crypt-sha512.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2010 + * The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Nolan Lum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "crypt.h" + +/* + * New password crypt. + */ + +char* +crypt_sha512(const char *pw, const char *salt) +{ + static const char *magic = "$4$"; /* Magic string for this + * algorithm. Easier to change + * when factored as constant. + */ + static char passwd[120], *p; + static const char *sp, *ep; + unsigned char final[SHA512_SIZE]; + int sl, i; + SHA512_CTX ctx; + unsigned long l; + + /* Refine the salt. */ + sp = salt; + + /* If it starts with the magic string, then skip that. */ + if (!strncmp(sp, magic, strlen(magic))) + sp += strlen(magic); + + /* Stop at the first '$', max 8 chars. */ + for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) + continue; + + /* Get the actual salt length. */ + sl = ep - sp; + + SHA512_Init(&ctx); + + /* Hash in the password first. */ + SHA512_Update(&ctx, pw, strlen(pw)); + + /* Then the magic string */ + SHA512_Update(&ctx, magic, sizeof(magic)); + + /* Then the raw salt. */ + SHA512_Update(&ctx, sp, sl); + + /* Finish and create the output string. */ + SHA512_Final(final, &ctx); + strcpy(passwd, magic); + strncat(passwd, sp, sl); + strcat(passwd, "$"); + + p = passwd + strlen(passwd); + + /* + * For-loop form of the algorithm in sha256.c; + * breaks the final output up into 3cols and then base64's each row. + */ + for (i = 0; i < 20; i++) { + l = (final[i] << 16) | (final[i + 21] << 8) | final[i + 42]; + _crypt_to64(p, l, 4); p += 4; + } + l = (final[20] << 16) | (final[41] << 8); + _crypt_to64(p, l, 4); p += 4; + *p = '\0'; + + /* Clear memory. */ + memset(final, 0, sizeof(final)); + + return (passwd); +} diff --git a/lib/libcrypt/crypt.3 b/lib/libcrypt/crypt.3 index f0681b2..a6c8057 100644 --- a/lib/libcrypt/crypt.3 +++ b/lib/libcrypt/crypt.3 @@ -63,6 +63,8 @@ Currently these include the .Tn NBS .Tn Data Encryption Standard (DES) , .Tn MD5 +.Tn SHA256 +.Tn SHA512 and .Tn Blowfish . The algorithm used will depend upon the format of the Salt (following @@ -176,6 +178,10 @@ Currently supported algorithms are: .It MD5 .It +SHA256 +.It +SHA512 +.It Blowfish .El .Pp @@ -210,7 +216,9 @@ Valid values are .\" NOTICE: Also make sure to update this, too, as well .\" .Ql des , -.Ql blf +.Ql blf , +.Ql sha256 , +.Ql sha512 , and .Ql md5 . .Pp diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c index 4d16ff1..764afab 100644 --- a/lib/libcrypt/crypt.c +++ b/lib/libcrypt/crypt.c @@ -57,6 +57,16 @@ static const struct { }, #endif { + "sha256", + crypt_sha256, + "$3$" + }, + { + "sha512", + crypt_sha512, + "$4$" + }, + { NULL, NULL } diff --git a/lib/libcrypt/crypt.h b/lib/libcrypt/crypt.h index c2f09c0..76c2a4e 100644 --- a/lib/libcrypt/crypt.h +++ b/lib/libcrypt/crypt.h @@ -30,10 +30,14 @@ /* magic sizes */ #define MD5_SIZE 16 +#define SHA256_SIZE 32 +#define SHA512_SIZE 64 char *crypt_des(const char *pw, const char *salt); char *crypt_md5(const char *pw, const char *salt); char *crypt_blowfish(const char *pw, const char *salt); +char *crypt_sha256(const char *pw, const char *salt); +char *crypt_sha512(const char *pw, const char *salt); extern void _crypt_to64(char *s, unsigned long v, int n); diff --git a/lib/pam_module/pam_unix/pam_unix.c b/lib/pam_module/pam_unix/pam_unix.c index a2cf30c..b7f1359 100644 --- a/lib/pam_module/pam_unix/pam_unix.c +++ b/lib/pam_module/pam_unix/pam_unix.c @@ -66,7 +66,7 @@ #include #include -#define PASSWORD_HASH "md5" +#define PASSWORD_HASH "sha256" #define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ #define SALTSIZE 32