1
/* crypto/des/fcrypt.c */
b'/* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au)'
0
2
* All rights reserved.
2
4
* This package is an SSL implementation written
3
5
* by Eric Young (eay@mincom.oz.au).
4
6
* The implementation was written so as to conform with Netscapes SSL.
6
8
* This library is free for commercial and non-commercial use as long as
7
9
* the following conditions are aheared to. The following conditions
8
10
* apply to all code found in this distribution, be it the RC4, RSA,
9
11
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
10
12
* included with this distribution is covered by the same copyright terms
11
13
* except that the holder is Tim Hudson (tjh@mincom.oz.au).
13
15
* Copyright remains Eric Young's, and as such any Copyright notices in
14
16
* the code are not to be removed.
15
17
* If this package is used in a product, Eric Young should be given attribution
16
18
* as the author of the parts of the library used.
17
19
* This can be in the form of a textual message at program startup or
18
20
* in documentation (online or textual) provided with the package.
20
22
* Redistribution and use in source and binary forms, with or without
21
23
* modification, are permitted provided that the following conditions
23
25
* 1. Redistributions of source code must retain the copyright
24
26
* notice, this list of conditions and the following disclaimer.
25
27
* 2. Redistributions in binary form must reproduce the above copyright
26
28
* notice, this list of conditions and the following disclaimer in the
27
29
* documentation and/or other materials provided with the distribution.
28
30
* 3. All advertising materials mentioning features or use of this software
29
31
* must display the following acknowledgement:
30
32
* "This product includes cryptographic software written by
31
33
* Eric Young (eay@mincom.oz.au)"
32
34
* The word 'cryptographic' can be left out if the rouines from the library
33
35
* being used are not cryptographic related :-).
34
36
* 4. If you include any Windows specific code (or a derivative thereof) from
35
37
* the apps directory (application code) you must include an acknowledgement:
36
38
* "This product includes software written by Tim Hudson (tjh@mincom.oz.au)"
38
40
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
39
41
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40
42
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41
43
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
42
44
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43
45
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44
46
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45
47
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46
48
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47
49
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
52
* The licence and distribution terms for any publically available version or
51
53
* derivative of this code cannot be changed. i.e. this code cannot simply be
52
54
* copied and put under another distribution licence
53
55
* [including the GNU Public Licence.]
55
57
* This version of crypt has been developed from my MIT compatable
57
59
* The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au
58
60
* eay@mincom.oz.au or eay@psych.psy.uq.oz.au
b'/* Modification by Jens Kupferschmidt (Cu)'
60
62
* I have included directive PARA for shared memory computers.
61
63
* I have included a directive LONGCRYPT to using this routine to cipher
62
64
* passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN
63
65
* definition is the maximum of lenght of password and can changed. I have
b'#define FCRYPT_MOD(R,u,t,E0,E1,tmp) \\'
b'\ttmp=(u<<16); u^=R^s[S ]; u^=tmp; \\'
b'\ttmp=(t<<16); t^=R^s[S+1]; t^=tmp'
b'#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\\'
b'#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\\'
b'\t(a)=(a)^(t)^(t>>(16-(n))))\\'
b'#define STATIC\tstatic'
b'/* It is really only FreeBSD that still suffers from MD5 based crypts */'
b'#define MD5_CRYPT_SUPPORT 1'
66
68
* ----------------------------------------------------------------------------
67
69
* "THE BEER-WARE LICENSE" (Revision 42):
68
70
* <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
69
71
* can do whatever you want with this stuff. If we meet some day, and you think
70
72
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
71
73
* ----------------------------------------------------------------------------
b'static unsigned char itoa64[] =\t\t/* 0 ... 63 => ascii - 64 */'
b'\t"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";'
b'\t\t*s++ = itoa64[v&0x3f];'
75
77
* Use MD5 for what it is best at...
b'\tregister const char *pw;'
b'\tregister const char *salt;'
b'\tstatic char\t*magic = "$1$";\t/*'
b'\t\t\t\t\t\t * This string is magic for'
b'\t\t\t\t\t\t * this algorithm. Having'
b'\t\t\t\t\t\t * it this way, we can get'
b'\t\t\t\t\t\t * get better later on'
b'\tstatic char passwd[120], *p;'
b'\tstatic const char *sp,*ep;'
b'\tunsigned char\tfinal[16];'
b'\t/* Refine the Salt first */'
b'\t/* If it starts with the magic string, then skip that */'
b'\tif(!strncmp(sp,magic,strlen(magic)))'
b'\t\tsp += strlen(magic);'
b"\t/* It stops at the first '$', max 8 chars */"
b"\tfor(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)"
b'\t/* get the length of the true salt */'
b'\t/* The password first, since that is what is most unknown */'
b'\tMD5Update(&ctx,pw,strlen(pw));'
b'\t/* Then our magic string */'
b'\tMD5Update(&ctx,magic,strlen(magic));'
b'\t/* Then the raw salt */'
b'\tMD5Update(&ctx,sp,sl);'
b'\t/* Then just as many characters of the MD5(pw,salt,pw) */'
b'\tMD5Update(&ctx1,pw,strlen(pw));'
b'\tMD5Update(&ctx1,sp,sl);'
b'\tMD5Update(&ctx1,pw,strlen(pw));'
b'\tMD5Final(final,&ctx1);'
b'\tfor(pl = strlen(pw); pl > 0; pl -= 16)'
b'\t\tMD5Update(&ctx,final,pl>16 ? 16 : pl);'
b"\t/* Don't leave anything around in vm they could use. */"
b'\tmemset(final,0,sizeof final);'
b'\t/* Then something really weird... */'
b'\tfor (j=0,i = strlen(pw); i ; i >>= 1)'
b'\t\t MD5Update(&ctx, final+j, 1);'
b'\t\t MD5Update(&ctx, pw+j, 1);'
b'\t/* Now make the output string */'
b'\tsnprintf (passwd, sizeof(passwd),'
b'\t\t "%s%.*s$", magic, sl, sp);'
b'\tMD5Final(final,&ctx);'
b"\t * and now, just to make sure things don't run too fast"
b'\t * On a 60 Mhz Pentium this takes 34 msec, so you would'
b'\t * need 30 seconds to build a 1000 entry dictionary...'
b'\tfor(i=0;i<1000;i++) {'
b'\t\t\tMD5Update(&ctx1,pw,strlen(pw));'
b'\t\t\tMD5Update(&ctx1,final,16);'
b'\t\t\tMD5Update(&ctx1,sp,sl);'
b'\t\t\tMD5Update(&ctx1,pw,strlen(pw));'
b'\t\t\tMD5Update(&ctx1,final,16);'
b'\t\t\tMD5Update(&ctx1,pw,strlen(pw));'
b'\t\tMD5Final(final,&ctx1);'
b'\tp = passwd + strlen(passwd);'
b'\tl = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;'
b'\tl = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;'
b'\tl = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;'
b'\tl = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;'
b'\tl = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;'
b'\tl = final[11] ; to64(p,l,2); p += 2;'
b"\t/* Don't leave anything around in vm they could use. */"
b'\tmemset(final,0,sizeof final);'
b'#endif /* MD5_CRYPT_SUPPORT */'
b'STATIC int fcrypt_body(DES_LONG *out0, DES_LONG *out1,'
b'\tdes_key_schedule ks, DES_LONG Eswap0, DES_LONG Eswap1);'
b'STATIC int fcrypt_body();'
b'/* Added more values to handle illegal salt values the way normal'
77
79
* crypt() implementations do. The patch was sent by
78
80
* Bjorn Gronvall <bg@sics.se>
b'static unsigned const char con_salt[128]={'
b'0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,'
b'0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,'
b'0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,'
b'0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,'
b'0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,'
b'0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01,'
b'0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,'
b'0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A,'
b'0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,'
b'0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,'
b'0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,'
b'0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24,'
b'0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,'
b'0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,'
b'0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,'
b'0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,'
b'static unsigned const char cov_2char[64]={'
b'0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,'
b'0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,'
b'0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,'
b'0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,'
b'0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,'
b'0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,'
b'0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,'
b'0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A'
b'char *des_crypt(const char *buf,const char *salt);'
b'char *crypt(const char *buf,const char *salt);'
b'char *des_crypt(buf,salt)'
b'\tstatic char buff[14];'
b'\tif (!strncmp(salt, "$1$", 3))'
b'\t\treturn crypt_md5(buf, salt);'
b'\treturn(des_fcrypt(buf,salt,buff));'
b'char *des_fcrypt(buf,salt,ret)'
b'\tunsigned int i,j,x,y;'
b'\tDES_LONG Eswap0,Eswap1;'
b'\tdes_key_schedule ks;'
b'\tunsigned char bb[9];'
b'\tunsigned char *b=bb;'
b'\t * If you call crypt("pwd","*") as often happens when you'
b'\t * have * as the pwd field in /etc/passwd, the function'
b'\t * returns *\\0XXXXXXXXX'
b'\t * The \\0 makes the string look like * so the pwd "*" would'
b'\t * crypt to "*". This was found when replacing the crypt in'
b'\t * our shared libraries. People found that the disbled'
b'\t * accounts effectivly had no passwd :-(. */'
b"\tx=ret[0]=((salt[0] == '\\0')?'A':salt[0]);"
b'\tEswap0=con_salt[x]<<2;'
b"\tx=ret[1]=((salt[1] == '\\0')?'A':salt[1]);"
b'\tEswap1=con_salt[x]<<6;'
b'\tdes_set_key((des_cblock *)(key),ks);'
b'\tfcrypt_body(&(out[0]),&(out[1]),ks,Eswap0,Eswap1);'
b'\tll=out[0]; l2c(ll,b);'
b'\tll=out[1]; l2c(ll,b);'
b'\tfor (i=2; i<13; i++)'
b'\t\tfor (j=0; j<6; j++)'
b'\t\t\tif (bb[y] & u) c|=1;'
b'\t\tret[i]=cov_2char[c];'
b'STATIC int fcrypt_body(out0, out1, ks, Eswap0, Eswap1)'
b'\tregister DES_LONG l,r,t,u;'
b'\tregister unsigned char *des_SP=(unsigned char *)des_SPtrans;'
b'\tregister DES_LONG *s;'
b'\tregister DES_LONG E0,E1;'
b'\tfor (j=0; j<25; j++)'
b'\t\tfor (i=0; i<32; i+=8)'
b'\t\t\tD_ENCRYPT(l,r,i+0); /* 1 */'
b'\t\t\tD_ENCRYPT(r,l,i+2); /* 2 */'
b'\t\t\tD_ENCRYPT(l,r,i+4); /* 3 */'
b'\t\t\tD_ENCRYPT(r,l,i+6); /* 4 */'
b'\t\tD_ENCRYPT(l,r, 0); /* 1 */'
b'\t\tD_ENCRYPT(r,l, 2); /* 2 */'
b'\t\tD_ENCRYPT(l,r, 4); /* 3 */'
b'\t\tD_ENCRYPT(r,l, 6); /* 4 */'
b'\t\tD_ENCRYPT(l,r, 8); /* 5 */'
b'\t\tD_ENCRYPT(r,l,10); /* 6 */'
b'\t\tD_ENCRYPT(l,r,12); /* 7 */'
b'\t\tD_ENCRYPT(r,l,14); /* 8 */'
b'\t\tD_ENCRYPT(l,r,16); /* 9 */'
b'\t\tD_ENCRYPT(r,l,18); /* 10 */'
b'\t\tD_ENCRYPT(l,r,20); /* 11 */'
b'\t\tD_ENCRYPT(r,l,22); /* 12 */'
b'\t\tD_ENCRYPT(l,r,24); /* 13 */'
b'\t\tD_ENCRYPT(r,l,26); /* 14 */'
b'\t\tD_ENCRYPT(l,r,28); /* 15 */'
b'\t\tD_ENCRYPT(r,l,30); /* 16 */'
b'\tl=ROTATE(l,3)&0xffffffffL;'
b'\tr=ROTATE(r,3)&0xffffffffL;'
b'\tPERM_OP(l,r,t, 1,0x55555555L);'
b'\tPERM_OP(r,l,t, 8,0x00ff00ffL);'
b'\tPERM_OP(l,r,t, 2,0x33333333L);'
b'\tPERM_OP(r,l,t,16,0x0000ffffL);'
b'\tPERM_OP(l,r,t, 4,0x0f0f0f0fL);'
b'\\ No newline at end of file'