1 /* crypto/des/fcrypt.c */
2 /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au)
5 * This package is an SSL implementation written
6 * by Eric Young (eay@mincom.oz.au).
7 * The implementation was written so as to conform with Netscapes SSL.
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@mincom.oz.au).
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@mincom.oz.au)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)"
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
62 * This version of crypt has been developed from my MIT compatable
64 * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au
65 * eay@mincom.oz.au or eay@psych.psy.uq.oz.au
68 /* Modification by Jens Kupferschmidt (Cu)
69 * I have included directive PARA for shared memory computers.
70 * I have included a directive LONGCRYPT to using this routine to cipher
71 * passwords with more than 8 bytes like HP-UX 10.x it used. The MAXPLEN
72 * definition is the maximum of lenght of password and can changed. I have
76 #define FCRYPT_MOD(R,u,t,E0,E1,tmp) \
80 tmp=(u<<16); u^=R^s[S ]; u^=tmp; \
81 tmp=(t<<16); t^=R^s[S+1]; t^=tmp
88 #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
93 #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
94 (a)=(a)^(t)^(t>>(16-(n))))\
102 /* It used to be Only FreeBSD that had MD5 based crypts, but now it's
103 * also the case on Redhat linux 6.0 and OpenBSD so we always include
104 * this code. That solves the problem of making the test program
105 * conditional as well.
108 #define MD5_CRYPT_SUPPORT 1
110 #if MD5_CRYPT_SUPPORT
112 * ----------------------------------------------------------------------------
113 * "THE BEER-WARE LICENSE" (Revision 42):
114 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
115 * can do whatever you want with this stuff. If we meet some day, and you think
116 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
117 * ----------------------------------------------------------------------------
125 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
126 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
135 *s++ = itoa64[v&0x3f];
143 * Use MD5 for what it is best at...
149 register const char *pw;
150 register const char *salt;
152 static char *magic = "$1$"; /*
153 * This string is magic for
154 * this algorithm. Having
155 * it this way, we can get
156 * get better later on
158 static char passwd[120], *p;
159 static const char *sp,*ep;
160 unsigned char final[16];
165 /* Refine the Salt first */
168 /* If it starts with the magic string, then skip that */
169 if(!strncmp(sp,magic,strlen(magic)))
172 /* It stops at the first '$', max 8 chars */
173 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
176 /* get the length of the true salt */
181 /* The password first, since that is what is most unknown */
182 MD5_Update(&ctx,pw,strlen(pw));
184 /* Then our magic string */
185 MD5_Update(&ctx,magic,strlen(magic));
187 /* Then the raw salt */
188 MD5_Update(&ctx,sp,sl);
190 /* Then just as many characters of the MD5(pw,salt,pw) */
192 MD5_Update(&ctx1,pw,strlen(pw));
193 MD5_Update(&ctx1,sp,sl);
194 MD5_Update(&ctx1,pw,strlen(pw));
195 MD5_Final(final,&ctx1);
196 for(pl = strlen(pw); pl > 0; pl -= 16)
197 MD5_Update(&ctx,final,pl>16 ? 16 : pl);
199 /* Don't leave anything around in vm they could use. */
200 memset(final,0,sizeof final);
202 /* Then something really weird... */
203 for (j=0,i = strlen(pw); i ; i >>= 1)
205 MD5_Update(&ctx, final+j, 1);
207 MD5_Update(&ctx, pw+j, 1);
209 /* Now make the output string */
210 strcpy(passwd, magic); /* sizeof(passwd) > sizeof(magic) */
211 strncat(passwd, sp, sl); /* ok, since sl <= 8 */
214 MD5_Final(final,&ctx);
217 * and now, just to make sure things don't run too fast
218 * On a 60 Mhz Pentium this takes 34 msec, so you would
219 * need 30 seconds to build a 1000 entry dictionary...
221 for(i=0;i<1000;i++) {
224 MD5_Update(&ctx1,pw,strlen(pw));
226 MD5_Update(&ctx1,final,16);
229 MD5_Update(&ctx1,sp,sl);
232 MD5_Update(&ctx1,pw,strlen(pw));
235 MD5_Update(&ctx1,final,16);
237 MD5_Update(&ctx1,pw,strlen(pw));
238 MD5_Final(final,&ctx1);
241 p = passwd + strlen(passwd);
243 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
244 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
245 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
246 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
247 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
248 l = final[11] ; to64(p,l,2); p += 2;
251 /* Don't leave anything around in vm they could use. */
252 memset(final,0,sizeof final);
256 #endif /* MD5_CRYPT_SUPPORT */
260 STATIC int fcrypt_body(DES_LONG *out0, DES_LONG *out1,
261 des_key_schedule ks, DES_LONG Eswap0, DES_LONG Eswap1);
265 STATIC int fcrypt_body();
269 /* Added more values to handle illegal salt values the way normal
270 * crypt() implementations do. The patch was sent by
271 * Bjorn Gronvall <bg@sics.se>
273 static unsigned const char con_salt[128]={
274 0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
275 0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,
276 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
277 0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,
278 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,
279 0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01,
280 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
281 0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A,
282 0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,
283 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,
284 0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,
285 0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24,
286 0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,
287 0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,
288 0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,
289 0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,
292 static unsigned const char cov_2char[64]={
293 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
294 0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,
295 0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,
296 0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,
297 0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,
298 0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,
299 0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,
300 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A
305 char *des_crypt(const char *buf,const char *salt);
307 char *crypt(const char *buf,const char *salt);
318 char *des_crypt(buf,salt)
320 char *crypt(buf,salt)
325 static char buff[14];
327 #if MD5_CRYPT_SUPPORT
328 if (!strncmp(salt, "$1$", 3))
329 return crypt_md5(buf, salt);
332 return(des_fcrypt(buf,salt,buff));
336 char *des_fcrypt(buf,salt,ret)
341 unsigned int i,j,x,y;
342 DES_LONG Eswap0,Eswap1;
351 * If you call crypt("pwd","*") as often happens when you
352 * have * as the pwd field in /etc/passwd, the function
353 * returns *\0XXXXXXXXX
354 * The \0 makes the string look like * so the pwd "*" would
355 * crypt to "*". This was found when replacing the crypt in
356 * our shared libraries. People found that the disbled
357 * accounts effectivly had no passwd :-(. */
358 x=ret[0]=((salt[0] == '\0')?'A':salt[0]);
359 Eswap0=con_salt[x]<<2;
360 x=ret[1]=((salt[1] == '\0')?'A':salt[1]);
361 Eswap1=con_salt[x]<<6;
376 des_set_key((des_cblock *)(key),ks);
377 fcrypt_body(&(out[0]),&(out[1]),ks,Eswap0,Eswap1);
379 ll=out[0]; l2c(ll,b);
380 ll=out[1]; l2c(ll,b);
404 STATIC int fcrypt_body(out0, out1, ks, Eswap0, Eswap1)
411 register DES_LONG l,r,t,u;
413 register unsigned char *des_SP=(unsigned char *)des_SPtrans;
415 register DES_LONG *s;
417 register DES_LONG E0,E1;
431 for (i=0; i<32; i+=8)
433 D_ENCRYPT(l,r,i+0); /* 1 */
434 D_ENCRYPT(r,l,i+2); /* 2 */
435 D_ENCRYPT(l,r,i+4); /* 3 */
436 D_ENCRYPT(r,l,i+6); /* 4 */
439 D_ENCRYPT(l,r, 0); /* 1 */
440 D_ENCRYPT(r,l, 2); /* 2 */
441 D_ENCRYPT(l,r, 4); /* 3 */
442 D_ENCRYPT(r,l, 6); /* 4 */
443 D_ENCRYPT(l,r, 8); /* 5 */
444 D_ENCRYPT(r,l,10); /* 6 */
445 D_ENCRYPT(l,r,12); /* 7 */
446 D_ENCRYPT(r,l,14); /* 8 */
447 D_ENCRYPT(l,r,16); /* 9 */
448 D_ENCRYPT(r,l,18); /* 10 */
449 D_ENCRYPT(l,r,20); /* 11 */
450 D_ENCRYPT(r,l,22); /* 12 */
451 D_ENCRYPT(l,r,24); /* 13 */
452 D_ENCRYPT(r,l,26); /* 14 */
453 D_ENCRYPT(l,r,28); /* 15 */
454 D_ENCRYPT(r,l,30); /* 16 */
460 l=ROTATE(l,3)&0xffffffffL;
461 r=ROTATE(r,3)&0xffffffffL;
463 PERM_OP(l,r,t, 1,0x55555555L);
464 PERM_OP(r,l,t, 8,0x00ff00ffL);
465 PERM_OP(l,r,t, 2,0x33333333L);
466 PERM_OP(r,l,t,16,0x0000ffffL);
467 PERM_OP(l,r,t, 4,0x0f0f0f0fL);