From 0cb1c5b095f3ccb2b3a2228a67aec0569258f62a Mon Sep 17 00:00:00 2001 From: brandon Date: Thu, 21 Jan 1999 13:50:09 +0000 Subject: Rewrite of crypt library to be more modular, and addition of the Secure Hashing Algorithm - 1 (SHA-1), along with the further refinement of what $x$salt$hash means. With this new crypt the following are all acceptable: $1$ $MD5$ $SHA1$ Note: $2$ is used by OpenBSD's Blowfish, which I considered adding as $BF$, but there is no actual need for it with SHA-1. However, somebody wishing to add OpenBSD password support could easilly add it in now. There is also a malloc_crypt() available in the library now, which behaves exactly the same as crypt(), but it uses a malloced buffer instead of a static buffer. However, this is not standard so will likely not be used much (at all). Also, for those interested I did a brief speed test Pentium 166/MMX, which shows the DES crypt to do approximately 2640 crypts a CPU second, MD5 to do about 62 crypts a CPU second and SHA1 to do about 18 crypts a CPU second. Reviewed by: Mark Murray --- lib/libcrypt/Makefile | 54 +++++----- lib/libcrypt/crypt-md5.c | 120 +++++++++++++++++++++ lib/libcrypt/crypt-shs.c | 122 +++++++++++++++++++++ lib/libcrypt/crypt.3 | 201 ++++++++++++++++++++++++++++++++++ lib/libcrypt/crypt.c | 276 ++++++++++++++++++++++++++--------------------- lib/libcrypt/crypt.h | 122 +++++++++++++++++++++ lib/libcrypt/descrypt.3 | 90 ++++++++++++++++ lib/libcrypt/shs.3 | 42 ++++++++ lib/libcrypt/shs.c | 243 +++++++++++++++++++++++++++++++++++++++++ lib/libcrypt/shs.h | 14 +++ 10 files changed, 1135 insertions(+), 149 deletions(-) create mode 100644 lib/libcrypt/crypt-md5.c create mode 100644 lib/libcrypt/crypt-shs.c create mode 100644 lib/libcrypt/crypt.3 create mode 100644 lib/libcrypt/crypt.h create mode 100644 lib/libcrypt/descrypt.3 create mode 100644 lib/libcrypt/shs.3 create mode 100644 lib/libcrypt/shs.c create mode 100644 lib/libcrypt/shs.h (limited to 'lib/libcrypt') diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile index 62c55e6..74babe8 100644 --- a/lib/libcrypt/Makefile +++ b/lib/libcrypt/Makefile @@ -1,57 +1,57 @@ # -# $Id: Makefile,v 1.13 1998/08/30 02:43:45 jb Exp $ +# $Id: Makefile,v 1.14 1998/09/02 15:09:15 bde Exp $ # -LCRYPTBASE= libcrypt -LSCRYPTBASE= libscrypt +SHLIB_MAJOR= 3 +.PATH: ${.CURDIR}/../../lib/libmd +SRCS= crypt.c crypt-md5.c md5c.c crypt-shs.c shs.c +MAN3= crypt.3 shs.3 descrypt.3 +CFLAGS+= -I${.CURDIR}/../libmd -DLIBC_SCCS +DESCRYPT= ${.CURDIR}/../../secure/lib/libcrypt/crypt-des.c + +## build exportable crypt or des crypt? +.if exists(${DESCRYPT}) && !defined(NOCRYPT) && !defined(NOSECURE) +.PATH: ${.CURDIR}/../../secure/lib/libcrypt +CIPHERTYPE= des +SRCS+= crypt-des.c +CFLAGS+= -I${.CURDIR} -DDES_CRYPT +.else +CIPHERTYPE= exp +.endif + +LIB=${CIPHERTYPE}crypt +LCRYPTBASE= libcrypt +LSCRYPTBASE= lib${LIB} .if ${OBJFORMAT} != elf LCRYPTSO= ${LCRYPTBASE}.so.${SHLIB_MAJOR}.${SHLIB_MINOR} LSCRYPTSO= ${LSCRYPTBASE}.so.${SHLIB_MAJOR}.${SHLIB_MINOR} .else +SONAME= ${LCRYPTBASE}.so.${SHLIB_MAJOR} LCRYPTSO= ${LCRYPTBASE}.so.${SHLIB_MAJOR} LSCRYPTSO= ${LSCRYPTBASE}.so.${SHLIB_MAJOR} .endif -# called libscrypt - for scramble crypt! -.PATH: ${.CURDIR}/../libmd -LIB= scrypt -SRCS= crypt.c md5c.c -CFLAGS+= -I${.CURDIR}/../libmd -DLIBC_SCCS - -.if ${OBJFORMAT} == elf -SONAME= ${LCRYPTBASE}.so.${SHLIB_MAJOR} -.endif - -# We only install the links if they do not already exist. -# This may have to be revised - afterinstall: .if !defined(NOPIC) @cd ${DESTDIR}${SHLIBDIR}; \ - if [ ! -e ${LCRYPTSO} ]; then \ rm -f ${LCRYPTSO}; \ ln -s ${LSCRYPTSO} ${LCRYPTSO}; \ - fi + rm -f ${LCRYPTBASE}.so.2; \ + ln -s ${LSCRYPTSO} ${LCRYPTBASE}.so.2 .endif .if !defined(NOPIC) && ${OBJFORMAT} == elf @cd ${DESTDIR}${SHLIBDIR}; \ - if [ ! -e ${LCRYPTBASE}.so ]; then \ rm -f ${LCRYPTBASE}.so; \ - ln -s ${LSCRYPTBASE}.so libcrypt.so; \ - fi + ln -s ${LSCRYPTBASE}.so libcrypt.so .endif @cd ${DESTDIR}${LIBDIR}; \ - if [ ! -e ${LCRYPTBASE}.a ]; then \ rm -f ${LCRYPTBASE}.a; \ - ln -s ${LSCRYPTBASE}.a libcrypt.a; \ - fi + ln -s ${LSCRYPTBASE}.a libcrypt.a .if !defined(NOPROFILE) @cd ${DESTDIR}${LIBDIR}; \ - if [ ! -e ${LCRYPTBASE}_p.a ]; then \ rm -f ${LCRYPTBASE}_p.a; \ - ln -s ${LSCRYPTBASE}_p.a libcrypt_p.a; \ - fi + ln -s ${LSCRYPTBASE}_p.a libcrypt_p.a .endif .include diff --git a/lib/libcrypt/crypt-md5.c b/lib/libcrypt/crypt-md5.c new file mode 100644 index 0000000..ba48583 --- /dev/null +++ b/lib/libcrypt/crypt-md5.c @@ -0,0 +1,120 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $FreeBSD$ + * + */ + +/* +// Modularized by Brandon Gillespie +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Header: /home/ncvs/src/lib/libcrypt/crypt.c,v 1.4 1996/07/12 18:56:01 jkh Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include "crypt.h" + +char * +crypt_md5(pw, pl, sp, sl, passwd, token) + register const unsigned char *pw; + const unsigned int pl; + register const unsigned char *sp; + const unsigned int sl; + char * passwd; + char * token; +{ + char *p; + unsigned char final[_MD5_SIZE]; + int i,j; + MD5_CTX ctx,ctx1; + unsigned long l; + + MD5Init(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Update(&ctx,pw,pl); + + /* Then our magic string */ + MD5Update(&ctx,(unsigned char *)token,strlen(token)); + + /* Then the raw salt */ + MD5Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1,pw,pl); + MD5Update(&ctx1,sp,sl); + MD5Update(&ctx1,pw,pl); + MD5Final(final,&ctx1); + for(i = pl; i > 0; i -= 16) + MD5Update(&ctx,final,i>16 ? 16 : i); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (j=0,i = pl; i ; i >>= 1) + if(i&1) + MD5Update(&ctx, final+j, 1); + else + MD5Update(&ctx, pw+j, 1); + + /* Now make the output string */ + strcpy(passwd, token); + strncat(passwd, (char *)sp, (int)sl); + strcat(passwd, "$"); + + MD5Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + MD5Init(&ctx1); + if(i & 1) + MD5Update(&ctx1,pw,pl); + else + MD5Update(&ctx1,final,_MD5_SIZE); + + if(i % 3) + MD5Update(&ctx1,sp,sl); + + if(i % 7) + MD5Update(&ctx1,pw,pl); + + if(i & 1) + MD5Update(&ctx1,final,_MD5_SIZE); + else + MD5Update(&ctx1,pw,pl); + MD5Final(final,&ctx1); + } + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; + l = final[11] ; to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} + diff --git a/lib/libcrypt/crypt-shs.c b/lib/libcrypt/crypt-shs.c new file mode 100644 index 0000000..5f8384c --- /dev/null +++ b/lib/libcrypt/crypt-shs.c @@ -0,0 +1,122 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $FreeBSD$ + * + */ + +/* +// Integrated SHA-1 crypt using PHK's MD5 code base. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Header: /home/ncvs/src/lib/libcrypt/crypt.c,v 1.4 1996/07/12 18:56:01 jkh Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include "crypt.h" + +char * +crypt_shs(pw, pl, sp, sl, passwd, token) + register const unsigned char *pw; + const unsigned int pl; + register const unsigned char *sp; + const unsigned int sl; + char * passwd; + char * token; +{ + char *p; + unsigned char final[_SHS_SIZE]; + int i,j; + SHS_CTX ctx,ctx1; + unsigned long l; + + shsInit(&ctx); + + /* The password first, since that is what is most unknown */ + shsUpdate(&ctx,pw,pl); + + /* Then our magic string */ + shsUpdate(&ctx,(unsigned char *)token, strlen(token)); + + /* Then the raw salt */ + shsUpdate(&ctx,sp,sl); + + /* Then just as many characters of the shs(pw,salt,pw) */ + shsInit(&ctx1); + shsUpdate(&ctx1,pw,pl); + shsUpdate(&ctx1,sp,sl); + shsUpdate(&ctx1,pw,pl); + shsFinal(&ctx1,final); + for(i = pl; i > 0; i -= _SHS_SIZE) + shsUpdate(&ctx,final,i>_SHS_SIZE ? _SHS_SIZE : i); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (j=0,i = pl; i ; i >>= 1) + if(i&1) + shsUpdate(&ctx, final+j, 1); + else + shsUpdate(&ctx, pw+j, 1); + + /* Now make the output string */ + strcpy(passwd, token); + strncat(passwd, (char *)sp, (int)sl); + strcat(passwd, "$"); + + shsFinal(&ctx,final); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + shsInit(&ctx1); + if(i & 1) + shsUpdate(&ctx1,pw,pl); + else + shsUpdate(&ctx1,final,_SHS_SIZE); + + if(i % 3) + shsUpdate(&ctx1,sp,sl); + + if(i % 7) + shsUpdate(&ctx1,pw,pl); + + if(i & 1) + shsUpdate(&ctx1,final,_SHS_SIZE); + else + shsUpdate(&ctx1,pw,pl); + shsFinal(&ctx1,final); + } + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[16]; to64(p,l,4); p += 4; + l = (final[ 5]<<16) | (final[11]<<8) | final[17]; to64(p,l,4); p += 4; + l = (final[18]<<8) | final[19]; to64(p,l,3); p += 3; + + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} + diff --git a/lib/libcrypt/crypt.3 b/lib/libcrypt/crypt.3 new file mode 100644 index 0000000..f07cf90 --- /dev/null +++ b/lib/libcrypt/crypt.3 @@ -0,0 +1,201 @@ +.\" FreeSec: libcrypt for NetBSD +.\" +.\" Copyright (c) 1994 David Burren +.\" All rights reserved. +.\" +.\" 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. +.\" 4. Neither the name of the author nor the names of other contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.\" Manual page, using -mandoc macros +.\" +.Dd January 19, 1997 +.Dt CRYPT 3 +.Os "FreeSec 1.0" +.Sh NAME +.Nm crypt +.Nd Trapdoor encryption +.Sh SYNOPSIS +.Ft char +.Fn *crypt "const char *key" "const char *salt" +.Ft char +.Fn *malloc_crypt "const char *key" "const char *salt" +.Sh DESCRIPTION +The +.Fn crypt +function performs password hashing with additional code added to +deter key search attempts. Different algorithms can be used to +in the hash. +.\" +.\" NOTICE: +.\" If you add more algorithms, make sure to update this list +.\" and the default used for the Traditional format, below. +.\" +Currently these include the +.Tn NBS +Data Encryption Standard (DES), MD5 or SHS. The algorithm +used will depend upon the format of the Salt--following the Modular +Crypt Format (MCF)--and if DES is installed or not. +.Pp +The first argument to +.Nm crypt +is the data to hash (usually a password), in a +.Dv null Ns -terminated +string. +The second is the salt, in one of three forms: +.Pp +.Bl -tag -width Traditional -compact -offset indent +.It Extended +If it begins with an underscore (``_'') then the DES Extended Format +is used in interpreting both the the key and the salt, as outlined below. +.It Modular +If it begins with the string ``$token$'' (where ``token'' is a digit or +alphanumeric token) 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). +.El +.Pp +The function +.Fn malloc_crypt +differs from +.Fn crypt +in not using a static buffer. The results are instead returned in a +string buffer allocated with +.Fn malloc . +.Pp +All routines are designed to be time-consuming. A brief test on a +Pentium 166/MMX shows the DES crypt to do approximately 2640 crypts +a CPU second, MD5 to do about 62 crypts a CPU second and SHA1 +to do about 18 crypts a CPU second. +.Ss DES Extended Format: +.Pp +The +.Ar key +is divided into groups of 8 characters (the last group is null-padded) +and the low-order 7 bits of each each character (56 bits per group) are +used to form the DES key as follows: +the first group of 56 bits becomes the initial DES key. +For each additional group, the XOR of the encryption of the current DES +key with itself and the group bits becomes the next DES key. +.Pp +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''. +This allows 24 bits for both +.Fa count +and +.Fa salt . +.Pp +Note: this should be clarified. +.Ss "Modular" crypt: +.Pp +If the salt begins with the string +.Fa $token$ +(where +.Fa token +is a digit or alphanumeric token) then the Modular Crypt Format is used. The +.Fa token +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 16 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. Any characters after the dollar sign are ignored. +.Pp +Currently supported tokens are: +.Pp +.Bl -tag -width 012345678 -compact -offset indent +.It MD5 +MD5 encryption--a token of 1 will also work. +.It SHA1 +SHA1 encryption. +.El +.Pp +Other crypt formats may be easilly added. An example salt would be: +.Bl -tag -offset indent +.It Cm "$SHA1$thesalt$rest" +.El +.Pp +.Ss "Traditional" crypt: +.Pp +The algorithm used will depend upon if DES is installed or not. If it is, +DES will be used. Otherwise, the best algorithm is used, which is currently +.\" +.\" NOTICE: Also make sure to update this +.\" +SHA-1. +.Pp +How the salt is used will depend upon the algorithm for the hash. For +best results, specify at least two characters of salt. +.Sh RETURN VALUES +.Pp +.Fn crypt +returns a pointer to the encrypted value on success, and NULL on failure. +Note: this is not a standard behaviour, AT&T +.Fn crypt +will always return a pointer to a string. +.Pp +.Fn malloc_crypt +returns a pointer to the encrypted value, which is in a dynamically +allocated buffer rather than a static buffer, using +.Fn malloc . +.Sh SEE ALSO +.Xr login 1 , +.Xr passwd 1 , +.Xr getpass 3 , +.Xr passwd 5 , +.Xr descrypt 3 , +.Xr shs 3 , +.Sh BUGS +The +.Fn crypt +function returns a pointer to static data, and subsequent calls to +.Fn crypt +will modify the same data. +.Fn malloc_crypt +can be used to avoid this problem--but it is not standard (so your code +will not be portable). +.Sh HISTORY +A rotor-based +.Fn crypt +function appeared in +.At v6 . +The current style +.Fn crypt +first appeared in +.At v7 . +.Pp +The DES section of the code (FreeSec 1.0) was developed outside the United +States of America as an unencumbered replacement for the U.S.-only NetBSD +libcrypt encryption library. +Users should be aware that this code (and programs staticly linked with it) +may not be exported from the U.S., although it apparently can be imported. +.Sh AUTHORS +Originally written by David Burren , later additions +and changes by Brandon Gillespie, Poul-henning Kamp and Mark R V Murray. +SHS Library written and Copyright 1995, 1996 by Paul C. Kocher. diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c index c0a8dc9..3d001a4 100644 --- a/lib/libcrypt/crypt.c +++ b/lib/libcrypt/crypt.c @@ -5,153 +5,185 @@ * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- - * - * $Id$ - * */ -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$Header: /home/ncvs/src/lib/libcrypt/crypt.c,v 1.6 1997/01/14 06:09:00 jkh Exp $"; -#endif /* LIBC_SCCS and not lint */ +/* + * It has since been changed by Brandon Gillespie, the end result is not + * too clean, but it is clear and modular; there is no need for crypt() + * to be optimized (and actually a desire for the opposite) so I am not + * overly concerned. + */ + +/* + * Assumptions made with the format of passwords: + * + * + Any password beginning with a dollar-sign is assumed to be in + * the Modular Crypt Format (MCF), namely: $tag$salt$hash. Any + * algorithms added will also use this format. Other MCF assumptions: + * + The algorithm tag (field 1) will be less than five characters + * long (yay, arbitrary limits). Anything longer is ignored. + * New algorithm names are not allowed to be fully numeric as + * anything fully numeric is mapped from other OS's not following + * our standard, and from older versions of this standard (such as + * $1$ for MD5 passwords, rather than $MD5$). + * + The salt can be up to 16 characters in length (more arbitrary + * limits). + * + An invalid or unrecognized algorithm tag will default to use the + * 'best' encryption method--whatever that may be at the time. + * + If the MCF is not specified, use the 'best' method, unless DES + * is installed--then use DES. + * + Any password beginning with an underscore '_' is assumed to be + * the Extended DES Format, which has its own salt requirements, + * and is not the same as the MCF. + * + Salt must be limited to the same ascii64 character set the hash + * is encoded in (namely "./0-9A-Za-z"). + */ #include #include +#include #include -#include -#include +#include + +#define _CRYPT_C_ + +#include "crypt.h" + +#ifndef TRUE +#define TRUE 1 +#endif -static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +#ifndef FALSE +#define FALSE 0 +#endif -static void to64 __P((char *, unsigned long, int)); +/* + * commonly used througout all algorithms + */ -static void +static unsigned char ascii64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +void to64(s, v, n) char *s; unsigned long v; int n; { -static void to64 __P((char *, unsigned long, int)); - while (--n >= 0) { - *s++ = itoa64[v&0x3f]; + *s++ = ascii64[v&0x3f]; v >>= 6; } } -/* - * UNIX password - * - * Use MD5 for what it is best at... - */ +static char * hash_word(password, salt, output) + const char *password; + const char *salt; + char *output; +{ + unsigned char spbuf[_CRYPT_MAX_SALT_LEN+1], + pwbuf[_CRYPT_OUTPUT_SIZE+1], + * ep, * sp, * pw; + unsigned int sl, pl, + tag = _CRYPT_DEFAULT_VERSION, + mcf = FALSE; + + memset(spbuf, 0, _CRYPT_MAX_SALT_LEN+1); + memset(pwbuf, 0, _CRYPT_MAX_SALT_LEN+1); + strncpy((char *) spbuf, (unsigned char *) salt, _CRYPT_MAX_SALT_LEN); + strncpy((char *) pwbuf, (unsigned char *) password, _CRYPT_OUTPUT_SIZE); + sp = &spbuf[0]; + pw = &pwbuf[0]; + pl = strlen((char *) pw); + + /* figure out what type of crypt is wanted */ + if (sp && sp[0] == '$') { + mcf = TRUE; + sp++; + if (strncasecmp((char *) sp, "MD5$", 4)==0) { + tag = _MD5_CRYPT; + sp += 4; + } else if (strncasecmp((char *) sp, "1$", 2)==0) { + tag = _MD5_CRYPT_OLD; + sp += 2; + } else if (strncasecmp((char *) sp, "SHA1$", 5)==0) { + tag = _SHS_CRYPT; + sp += 5; + } else { + tag = _CRYPT_DEFAULT_VERSION; + while (*sp && *sp != '$') + sp++; + if (*sp == '$') + sp++; + } + } + + /* Refine the salt. Go to the end, it stops at the first '$' or NULL */ + for (ep=sp; *ep && *ep != '$'; ep++) + continue; + + /* we have to do this so we dont overflow _PASSWORD_LEN */ + if ((ep - sp) > 16) { + sl = 16; + sp[16] = (char) NULL; + } else { + sl = ep - sp; + } + + switch (tag) { + case _MD5_CRYPT_OLD: + return crypt_md5(pw, pl, sp, sl, output, "$1$"); + case _MD5_CRYPT: + return crypt_md5(pw, pl, sp, sl, output, "$MD5$"); +#ifdef DES_CRYPT + case _DES_CRYPT: + return crypt_des(pw, pl, sp, sl, output, ""); +#endif + /* dropping a DES password through will likely cause problems, + but at least crypt() will return as it says it will (we cannot + return an error condition) */ + case _SHS_CRYPT: + default: + return crypt_shs(pw, pl, sp, sl, output, "$SHA1$"); + } +} char * -crypt(pw, salt) - register const char *pw; - register const char *salt; +crypt(password, salt) + const char *password; + const char *salt; { - static char *magic = "$1$"; /* - * This string is magic for - * this algorithm. Having - * it this way, we can get - * get better later on - */ - static char passwd[120], *p; - static const char *sp,*ep; - unsigned char final[16]; - int sl,pl,i,j; - MD5_CTX ctx,ctx1; - unsigned long l; - - /* Refine the Salt first */ - sp = salt; - - /* If it starts with the magic string, then skip that */ - if(!strncmp(sp,magic,strlen(magic))) - sp += strlen(magic); - - /* It stops at the first '$', max 8 chars */ - for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) - continue; - - /* get the length of the true salt */ - sl = ep - sp; - - MD5Init(&ctx); - - /* The password first, since that is what is most unknown */ - MD5Update(&ctx,pw,strlen(pw)); - - /* Then our magic string */ - MD5Update(&ctx,magic,strlen(magic)); - - /* Then the raw salt */ - MD5Update(&ctx,sp,sl); - - /* Then just as many characters of the MD5(pw,salt,pw) */ - MD5Init(&ctx1); - MD5Update(&ctx1,pw,strlen(pw)); - MD5Update(&ctx1,sp,sl); - MD5Update(&ctx1,pw,strlen(pw)); - MD5Final(final,&ctx1); - for(pl = strlen(pw); pl > 0; pl -= 16) - MD5Update(&ctx,final,pl>16 ? 16 : pl); - - /* Don't leave anything around in vm they could use. */ - memset(final,0,sizeof final); - - /* Then something really weird... */ - for (i = strlen(pw); i ; i >>= 1) - if(i&1) - MD5Update(&ctx, final, 1); - else - MD5Update(&ctx, pw, 1); - - /* Now make the output string */ - strcpy(passwd,magic); - strncat(passwd,sp,sl); - strcat(passwd,"$"); - - MD5Final(final,&ctx); - - /* - * and now, just to make sure things don't run too fast - * On a 60 Mhz Pentium this takes 34 msec, so you would - * need 30 seconds to build a 1000 entry dictionary... - */ - for(i=0;i<1000;i++) { - MD5Init(&ctx1); - if(i & 1) - MD5Update(&ctx1,pw,strlen(pw)); - else - MD5Update(&ctx1,final,16); - - if(i % 3) - MD5Update(&ctx1,sp,sl); - - if(i % 7) - MD5Update(&ctx1,pw,strlen(pw)); - - if(i & 1) - MD5Update(&ctx1,final,16); - else - MD5Update(&ctx1,pw,strlen(pw)); - MD5Final(final,&ctx1); - } + static char output[_CRYPT_OUTPUT_SIZE]; + + return hash_word(password, salt, output); +} + +char * +malloc_crypt(password, salt) + const char *password; + const char *salt; +{ + char * output; + + output = (char *) malloc(sizeof(char) * _CRYPT_OUTPUT_SIZE); + return hash_word(password, salt, output); +} + +int +match_crypted(possible, crypted) + const char * possible, + * crypted; +{ + char * pc; + int match; - p = passwd + strlen(passwd); + pc = malloc_crypt(possible, crypted); - l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; - l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; - l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; - l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; - l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; - l = final[11] ; to64(p,l,2); p += 2; - *p = '\0'; + match = !strcmp(pc, crypted); - /* Don't leave anything around in vm they could use. */ - memset(final,0,sizeof final); + free(pc); - return passwd; + return match; } +#undef _CRYPT_C_ diff --git a/lib/libcrypt/crypt.h b/lib/libcrypt/crypt.h new file mode 100644 index 0000000..3b43407 --- /dev/null +++ b/lib/libcrypt/crypt.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 1996 + * Brandon Gillespie. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY Brandon Gillespie 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 Brandon Gillespie 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. + * + */ + +/* +// -------------------------------------------------------------------------- +// to add a new algorithm, have it export the function 'crypt_' +// (where is whichever algorithm, such as 'des' or 'md5), with +// the arguments ordered as follows, and the return value 'char *': +// +// register const unsigned char * -- word to encrypt +// const unsigned int -- length of word to encrypt +// register const unsigned char * -- salt to encrypt with +// const unsigned int -- salt length +// char * -- output buffer, _CRYPT_OUTPUT_SIZE max +// char * -- identifier token +// +// such as: +// +// char * +// crypt_des(register const unsigned char *pw, +// const unsigned int pl, +// register const unsigned char *sp, +// const unsigned int sl, +// char * passwd, +// char * token); +// +// Prototype the function below, include libraries here. +// You can use the macro CRYPT_HOOK() to make it easy. +*/ + +#include +#include +#include "shs.h" + +#define _DES_CRYPT 0 +#define _MD5_CRYPT 1 +#define _MD5_CRYPT_OLD 3 +#define _BF_CRYPT 2 +#define _BF_CRYPT_OpenBSD 4 +#define _SHS_CRYPT 5 + +/* +// -------------------------------------------------------------------------- +// Prototypes +*/ + +#define _CRYPT_HOOK(_type_) \ + char * crypt_ ## _type_ ( \ + register const unsigned char * pw, \ + const unsigned int pl, \ + register const unsigned char * sw, \ + const unsigned int sp, \ + char * passwd, \ + char * token) + +#ifdef DES_CRYPT +_CRYPT_HOOK(des); +#endif + +_CRYPT_HOOK(md5); +_CRYPT_HOOK(shs); + +#undef _CRYPT_HOOK + +/* +// -------------------------------------------------------------------------- +// What is the default? +*/ +#ifdef _CRYPT_DEFAULT_DES + +/* use the 'best' encryption */ +/* currently SHA-1 */ +#define _CRYPT_DEFAULT_VERSION _SHS_CRYPT + +#else + +/* else use DES encryption */ +#define _CRYPT_DEFAULT_VERSION _DES_CRYPT + +#endif + +/* +// -------------------------------------------------------------------------- +// other unimportant magic, enlarge as algorithms warrant, do not reduce. +*/ + +/* largest size of encrypted password */ +#define _CRYPT_OUTPUT_SIZE _PASSWORD_LEN +#define _CRYPT_MAX_SALT_LEN 24 /* token=5 salt=16 extra=4 */ + +/* magic sizes not defined elsewhere, cleaner through defs */ +#define _MD5_SIZE 16 +#define _SHS_SIZE 20 + +#ifndef _CRYPT_C_ +extern void to64(char * s, unsigned long v, int n); +#endif + diff --git a/lib/libcrypt/descrypt.3 b/lib/libcrypt/descrypt.3 new file mode 100644 index 0000000..c028b19 --- /dev/null +++ b/lib/libcrypt/descrypt.3 @@ -0,0 +1,90 @@ +.\" FreeSec: libcrypt for NetBSD +.\" +.\" Copyright (c) 1994 David Burren +.\" All rights reserved. +.\" +.\" 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. +.\" 4. Neither the name of the author nor the names of other contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.\" Manual page, using -mandoc macros +.\" +.Dd January 19, 1997 +.Dt DES 3 +.Os "FreeSec 1.0" +.Sh NAME +.Nm des +.Nd Trapdoor encryption +.Sh DESCRIPTION +.Pp +The +.Fa salt +introduces disorder in the +.Tn DES +algorithm in one of 16777216 or 4096 possible ways +(ie. with 24 or 12 bits: if bit +.Em i +of the +.Ar salt +is set, then bits +.Em i +and +.Em i+24 +are swapped in the +.Tn DES +E-box output). +.Pp +The DES key is used to encrypt a 64-bit constant using +.Ar count +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 +.Ar salt +followed by the encoded 64-bit encryption. +.Sh SEE ALSO +.Xr crypt 3 +.Sh AVAILABILITY +.Pp +DES Crypt is only available if it has been added. It is not available +by default. +.Sh HISTORY +A rotor-based +.Fn crypt +function appeared in +.At v6 . +The current style +.Fn crypt +first appeared in +.At v7 . +.Pp +The DES section of the code (FreeSec 1.0) was developed outside the United +States of America as an unencumbered replacement for the U.S.-only NetBSD +libcrypt encryption library. +Users should be aware that this code (and programs staticly linked with it) +may not be exported from the U.S., although it apparently can be imported. +.Sh AUTHORS +David Burren diff --git a/lib/libcrypt/shs.3 b/lib/libcrypt/shs.3 new file mode 100644 index 0000000..6db63dee --- /dev/null +++ b/lib/libcrypt/shs.3 @@ -0,0 +1,42 @@ +.\" SHS 180-1 Reference Implementation (with unrolled loops) +.\" Copyright 1995-6 by Paul C. Kocher. +.\" +.\" This file is provided as-is, without warranty of any kind; +.\" use at your own risk. This file may be copied and used, +.\" even for commercial purposes, for free. For information, +.\" updates, updates, or consulting help, send e-mail to the +.\" author at pck@cryptography.com. +.\" +.\" EXPORT STATUS: In informal discussions, the U.S. National +.\" Security Agency has indicated to me that source code for +.\" can be exported from the U.S. freely, but programs using +.\" or incorporating this code may be restricted. Please make +.\" sure you understand the applicable export regulations +.\" before doing any work with cryptography. +.\" +.\" For links to other cryptography source code, papers, etc. see +.\" http://www.cryptography.com. +.\" +.Dd December 54, 1996 +.Dt SHS 3 +.Sh NAME +.Nm shs +.Nd encryption +.Sh DESCRIPTION +.Pp +EXPORT STATUS: In informal discussions, the U.S. National +Security Agency has indicated to me that source code for +can be exported from the U.S. freely, but programs using +or incorporating this code may be restricted. Please make +sure you understand the applicable export regulations +before doing any work with cryptography. +.Sh SEE ALSO +.Xr crypt 3 +.Sh AUTHOR +This file is provided as-is, without warranty of any kind; +use at your own risk. This file may be copied and used, +even for commercial purposes, for free. For information, +updates, updates, or consulting help, send e-mail to the +author at pck@cryptography.com +.Pp +Copyright 1995-6 by Paul C. Kocher. diff --git a/lib/libcrypt/shs.c b/lib/libcrypt/shs.c new file mode 100644 index 0000000..b382a24 --- /dev/null +++ b/lib/libcrypt/shs.c @@ -0,0 +1,243 @@ +/* + ******************************************************************** + * SHS 180-1 Reference Implementation (with unrolled loops) * + * Copyright 1995-6 by Paul C. Kocher. * + * * + * This file is provided as-is, without warranty of any kind; * + * use at your own risk. This file may be copied and used, * + * even for commercial purposes, for free. For information, * + * updates, updates, or consulting help, send e-mail to the * + * author at pck@cryptography.com. * + * * + * EXPORT STATUS: In informal discussions, the U.S. National * + * Security Agency has indicated to me that source code for * + * can be exported from the U.S. freely, but programs using * + * or incorporating this code may be restricted. Please make * + * sure you understand the applicable export regulations * + * before doing any work with cryptography. * + * * + * For links to other cryptography source code, papers, etc. see * + * http://www.cryptography.com. * + ******************************************************************** + */ + +#include "shs.h" + +static void shsCompress(SHS_CTX *ctx); + +#define SHS_ROTL(X,n) (((X) << (n)) | ((X) >> (32-(n)))) +#define SHS_F1(X,Y,Z) ((((Y)^(Z))&(X))^(Z)) +#define SHS_F2(X,Y,Z) ((X)^(Y)^(Z)) +#define SHS_F3(X,Y,Z) (((X)&(Y))|((Z)&((X)|(Y)))) +#define SHS_F4(X,Y,Z) ((X)^(Y)^(Z)) + + +/* + * SHS: Initialize context + */ +void shsInit(SHS_CTX *ctx) { + ctx->lenW = 0; + ctx->sizeHi = ctx->sizeLo = 0; + + /* + * Initialize H with constants from FIPS180-1. + */ + ctx->H[0] = 0x67452301L; + ctx->H[1] = 0xefcdab89L; + ctx->H[2] = 0x98badcfeL; + ctx->H[3] = 0x10325476L; + ctx->H[4] = 0xc3d2e1f0L; +} + + +/* + * SHS: Add data to context. + */ +void shsUpdate(SHS_CTX *ctx, const unsigned char * dataIn, int len) { + /* + * Read the data into W and process blocks as they get full + * + * NOTE: The shifts can be eliminated on big-endian machines, since + * the byte-to-word transformation can be done with a copy. In + * assembly language on 80486+ computers, the BSWAP instruction + * can be used. + */ + ctx->sizeLo += 8*len; + ctx->sizeHi += (ctx->sizeLo < 8*len) + (len >> 29); + while (len--) { + ctx->W[ctx->lenW / 4] <<= 8; + ctx->W[ctx->lenW / 4] |= *(dataIn++); + if (((++ctx->lenW) & 63) == 0) { + shsCompress(ctx); + ctx->lenW = 0; + } + } +} + + +/* + * SHS: Generate hash value from context + */ +void shsFinal(SHS_CTX * ctx, unsigned char hashOut[20]) { + static unsigned char bulk_pad[64] = { 0x80,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + unsigned char length_pad[8]; + int i; + + /* + * Pad with a binary 1 (e.g. 0x80), then zeroes, then length + */ + length_pad[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); + length_pad[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); + length_pad[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); + length_pad[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); + length_pad[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); + length_pad[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); + length_pad[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); + length_pad[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); + shsUpdate(ctx, bulk_pad, ((56+64) - ctx->lenW) & 63); + shsUpdate(ctx, length_pad, 8); + + /* + * Output hash + */ + for (i = 0; i < 5; i++) { + *(hashOut++) = ((unsigned char)(ctx->H[i] >> 24)) & 255; + *(hashOut++) = ((unsigned char)(ctx->H[i] >> 16)) & 255; + *(hashOut++) = ((unsigned char)(ctx->H[i] >> 8)) & 255; + *(hashOut++) = ((unsigned char)(ctx->H[i] )) & 255; + } + + /* + * Re-initialize the context (also zeroizes contents) + */ + shsInit(ctx); +} + + +/* + * SHS: Hash a block in memory + */ +void shsBlock(const unsigned char *dataIn, int len, unsigned char hashOut[20]) { + SHS_CTX ctx; + + shsInit(&ctx); + shsUpdate(&ctx, dataIn, len); + shsFinal(&ctx, hashOut); +} + + +/* + * SHS: Compression function, unrolled. + */ +static void shsCompress(SHS_CTX *ctx) { + int t; + register unsigned long A,B,C,D,E; + + /* + * This can be moved into the main code block below, but doing + * so can cause some compilers to run out of registers and resort + * to storing intermediates in RAM. + */ + for (t = 16; t <= 79; t++) + ctx->W[t] = + SHS_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); + + A = ctx->H[0]; + B = ctx->H[1]; + C = ctx->H[2]; + D = ctx->H[3]; + E = ctx->H[4]; + + E = SHS_ROTL(A,5)+SHS_F1(B,C,D)+E+ctx->W[ 0]+0x5a827999L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F1(A,B,C)+D+ctx->W[ 1]+0x5a827999L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F1(E,A,B)+C+ctx->W[ 2]+0x5a827999L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F1(D,E,A)+B+ctx->W[ 3]+0x5a827999L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F1(C,D,E)+A+ctx->W[ 4]+0x5a827999L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F1(B,C,D)+E+ctx->W[ 5]+0x5a827999L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F1(A,B,C)+D+ctx->W[ 6]+0x5a827999L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F1(E,A,B)+C+ctx->W[ 7]+0x5a827999L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F1(D,E,A)+B+ctx->W[ 8]+0x5a827999L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F1(C,D,E)+A+ctx->W[ 9]+0x5a827999L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F1(B,C,D)+E+ctx->W[10]+0x5a827999L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F1(A,B,C)+D+ctx->W[11]+0x5a827999L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F1(E,A,B)+C+ctx->W[12]+0x5a827999L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F1(D,E,A)+B+ctx->W[13]+0x5a827999L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F1(C,D,E)+A+ctx->W[14]+0x5a827999L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F1(B,C,D)+E+ctx->W[15]+0x5a827999L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F1(A,B,C)+D+ctx->W[16]+0x5a827999L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F1(E,A,B)+C+ctx->W[17]+0x5a827999L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F1(D,E,A)+B+ctx->W[18]+0x5a827999L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F1(C,D,E)+A+ctx->W[19]+0x5a827999L; C=SHS_ROTL(C,30); + + E = SHS_ROTL(A,5)+SHS_F2(B,C,D)+E+ctx->W[20]+0x6ed9eba1L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F2(A,B,C)+D+ctx->W[21]+0x6ed9eba1L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F2(E,A,B)+C+ctx->W[22]+0x6ed9eba1L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F2(D,E,A)+B+ctx->W[23]+0x6ed9eba1L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F2(C,D,E)+A+ctx->W[24]+0x6ed9eba1L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F2(B,C,D)+E+ctx->W[25]+0x6ed9eba1L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F2(A,B,C)+D+ctx->W[26]+0x6ed9eba1L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F2(E,A,B)+C+ctx->W[27]+0x6ed9eba1L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F2(D,E,A)+B+ctx->W[28]+0x6ed9eba1L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F2(C,D,E)+A+ctx->W[29]+0x6ed9eba1L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F2(B,C,D)+E+ctx->W[30]+0x6ed9eba1L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F2(A,B,C)+D+ctx->W[31]+0x6ed9eba1L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F2(E,A,B)+C+ctx->W[32]+0x6ed9eba1L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F2(D,E,A)+B+ctx->W[33]+0x6ed9eba1L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F2(C,D,E)+A+ctx->W[34]+0x6ed9eba1L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F2(B,C,D)+E+ctx->W[35]+0x6ed9eba1L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F2(A,B,C)+D+ctx->W[36]+0x6ed9eba1L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F2(E,A,B)+C+ctx->W[37]+0x6ed9eba1L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F2(D,E,A)+B+ctx->W[38]+0x6ed9eba1L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F2(C,D,E)+A+ctx->W[39]+0x6ed9eba1L; C=SHS_ROTL(C,30); + + E = SHS_ROTL(A,5)+SHS_F3(B,C,D)+E+ctx->W[40]+0x8f1bbcdcL; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F3(A,B,C)+D+ctx->W[41]+0x8f1bbcdcL; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F3(E,A,B)+C+ctx->W[42]+0x8f1bbcdcL; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F3(D,E,A)+B+ctx->W[43]+0x8f1bbcdcL; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F3(C,D,E)+A+ctx->W[44]+0x8f1bbcdcL; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F3(B,C,D)+E+ctx->W[45]+0x8f1bbcdcL; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F3(A,B,C)+D+ctx->W[46]+0x8f1bbcdcL; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F3(E,A,B)+C+ctx->W[47]+0x8f1bbcdcL; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F3(D,E,A)+B+ctx->W[48]+0x8f1bbcdcL; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F3(C,D,E)+A+ctx->W[49]+0x8f1bbcdcL; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F3(B,C,D)+E+ctx->W[50]+0x8f1bbcdcL; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F3(A,B,C)+D+ctx->W[51]+0x8f1bbcdcL; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F3(E,A,B)+C+ctx->W[52]+0x8f1bbcdcL; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F3(D,E,A)+B+ctx->W[53]+0x8f1bbcdcL; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F3(C,D,E)+A+ctx->W[54]+0x8f1bbcdcL; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F3(B,C,D)+E+ctx->W[55]+0x8f1bbcdcL; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F3(A,B,C)+D+ctx->W[56]+0x8f1bbcdcL; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F3(E,A,B)+C+ctx->W[57]+0x8f1bbcdcL; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F3(D,E,A)+B+ctx->W[58]+0x8f1bbcdcL; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F3(C,D,E)+A+ctx->W[59]+0x8f1bbcdcL; C=SHS_ROTL(C,30); + + E = SHS_ROTL(A,5)+SHS_F4(B,C,D)+E+ctx->W[60]+0xca62c1d6L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F4(A,B,C)+D+ctx->W[61]+0xca62c1d6L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F4(E,A,B)+C+ctx->W[62]+0xca62c1d6L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F4(D,E,A)+B+ctx->W[63]+0xca62c1d6L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F4(C,D,E)+A+ctx->W[64]+0xca62c1d6L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F4(B,C,D)+E+ctx->W[65]+0xca62c1d6L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F4(A,B,C)+D+ctx->W[66]+0xca62c1d6L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F4(E,A,B)+C+ctx->W[67]+0xca62c1d6L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F4(D,E,A)+B+ctx->W[68]+0xca62c1d6L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F4(C,D,E)+A+ctx->W[69]+0xca62c1d6L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F4(B,C,D)+E+ctx->W[70]+0xca62c1d6L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F4(A,B,C)+D+ctx->W[71]+0xca62c1d6L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F4(E,A,B)+C+ctx->W[72]+0xca62c1d6L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F4(D,E,A)+B+ctx->W[73]+0xca62c1d6L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F4(C,D,E)+A+ctx->W[74]+0xca62c1d6L; C=SHS_ROTL(C,30); + E = SHS_ROTL(A,5)+SHS_F4(B,C,D)+E+ctx->W[75]+0xca62c1d6L; B=SHS_ROTL(B,30); + D = SHS_ROTL(E,5)+SHS_F4(A,B,C)+D+ctx->W[76]+0xca62c1d6L; A=SHS_ROTL(A,30); + C = SHS_ROTL(D,5)+SHS_F4(E,A,B)+C+ctx->W[77]+0xca62c1d6L; E=SHS_ROTL(E,30); + B = SHS_ROTL(C,5)+SHS_F4(D,E,A)+B+ctx->W[78]+0xca62c1d6L; D=SHS_ROTL(D,30); + A = SHS_ROTL(B,5)+SHS_F4(C,D,E)+A+ctx->W[79]+0xca62c1d6L; C=SHS_ROTL(C,30); + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} + diff --git a/lib/libcrypt/shs.h b/lib/libcrypt/shs.h new file mode 100644 index 0000000..6d8959e --- /dev/null +++ b/lib/libcrypt/shs.h @@ -0,0 +1,14 @@ + +typedef struct { + unsigned long H[5]; + unsigned long W[80]; + int lenW; + unsigned long sizeHi,sizeLo; +} SHS_CTX; + + +void shsInit(SHS_CTX *ctx); +void shsUpdate(SHS_CTX *ctx, const unsigned char *dataIn, int len); +void shsFinal(SHS_CTX *ctx, unsigned char hashOut[20]); +void shsBlock(const unsigned char *dataIn, int len, unsigned char hashOut[20]); + -- cgit v1.1