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
This commit is contained in:
Brandon Gillespie 1999-01-21 13:50:09 +00:00
parent a102abb259
commit da5c7089a3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=42981
10 changed files with 1136 additions and 150 deletions

View File

@ -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 <bsd.lib.mk>

120
lib/libcrypt/crypt-md5.c Normal file
View File

@ -0,0 +1,120 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> 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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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;
}

122
lib/libcrypt/crypt-shs.c Normal file
View File

@ -0,0 +1,122 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> 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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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;
}

201
lib/libcrypt/crypt.3 Normal file
View File

@ -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 <davidb@werj.com.au>, 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.

View File

@ -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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <md5.h>
#include <string.h>
#include <ctype.h>
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
#define _CRYPT_C_
static void to64 __P((char *, unsigned long, int));
#include "crypt.h"
static void
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* commonly used througout all algorithms
*/
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...
*/
char *
crypt(pw, salt)
register const char *pw;
register const char *salt;
static char * hash_word(password, salt, output)
const char *password;
const char *salt;
char *output;
{
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;
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;
/* Refine the Salt first */
sp = salt;
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);
/* If it starts with the magic string, then skip that */
if(!strncmp(sp,magic,strlen(magic)))
sp += strlen(magic);
/* 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++;
}
}
/* It stops at the first '$', max 8 chars */
for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
continue;
/* Refine the salt. Go to the end, it stops at the first '$' or NULL */
for (ep=sp; *ep && *ep != '$'; ep++)
continue;
/* get the length of the true salt */
sl = ep - sp;
/* 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;
}
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);
}
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;
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(password, salt)
const char *password;
const char *salt;
{
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;
pc = malloc_crypt(possible, crypted);
match = !strcmp(pc, crypted);
free(pc);
return match;
}
#undef _CRYPT_C_

122
lib/libcrypt/crypt.h Normal file
View File

@ -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_<algo>'
// (where <algo> 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 <md5.h>
#include <pwd.h>
#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

90
lib/libcrypt/descrypt.3 Normal file
View File

@ -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 <davidb@werj.com.au>

42
lib/libcrypt/shs.3 Normal file
View File

@ -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.

243
lib/libcrypt/shs.c Normal file
View File

@ -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;
}

14
lib/libcrypt/shs.h Normal file
View File

@ -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]);