remove gcc34
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / des / fcrypt.c
blobc88d137f9c355b69f6c1278c3c86f65e800638a5
1 /* crypto/des/fcrypt.c */
2 /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au)
3 * All rights reserved.
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.
8 *
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
25 * are met:
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
51 * SUCH DAMAGE.
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.]
59 #include <stdio.h>
61 /* Eric Young.
62 * This version of crypt has been developed from my MIT compatable
63 * DES library.
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
73 * defined 24.
76 #define FCRYPT_MOD(R,u,t,E0,E1,tmp) \
77 u=R>>16; \
78 t=R^u; \
79 u=t&E0; t=t&E1; \
80 tmp=(u<<16); u^=R^s[S ]; u^=tmp; \
81 tmp=(t<<16); t^=R^s[S+1]; t^=tmp
83 #define DES_FCRYPT
84 #include "des_locl.h"
85 #undef DES_FCRYPT
87 #undef PERM_OP
88 #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
89 (b)^=(t),\
90 (a)^=((t)<<(n)))
92 #undef HPERM_OP
93 #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
94 (a)=(a)^(t)^(t>>(16-(n))))\
96 #ifdef PARA
97 #define STATIC
98 #else
99 #define STATIC static
100 #endif
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 * ----------------------------------------------------------------------------
120 #ifdef HAVE_CONFIG_H
121 #include <config.h>
122 #endif
123 #include <md5.h>
125 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
126 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
128 static void
129 to64(s, v, n)
130 char *s;
131 unsigned long v;
132 int n;
134 while (--n >= 0) {
135 *s++ = itoa64[v&0x3f];
136 v >>= 6;
141 * UNIX password
143 * Use MD5 for what it is best at...
146 static
147 char *
148 crypt_md5(pw, salt)
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];
161 int sl,pl,i,j;
162 MD5_CTX ctx,ctx1;
163 unsigned long l;
165 /* Refine the Salt first */
166 sp = salt;
168 /* If it starts with the magic string, then skip that */
169 if(!strncmp(sp,magic,strlen(magic)))
170 sp += strlen(magic);
172 /* It stops at the first '$', max 8 chars */
173 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
174 continue;
176 /* get the length of the true salt */
177 sl = ep - sp;
179 MD5_Init(&ctx);
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) */
191 MD5_Init(&ctx1);
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)
204 if(i&1)
205 MD5_Update(&ctx, final+j, 1);
206 else
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 */
212 strcat(passwd, "$");
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++) {
222 MD5_Init(&ctx1);
223 if(i & 1)
224 MD5_Update(&ctx1,pw,strlen(pw));
225 else
226 MD5_Update(&ctx1,final,16);
228 if(i % 3)
229 MD5_Update(&ctx1,sp,sl);
231 if(i % 7)
232 MD5_Update(&ctx1,pw,strlen(pw));
234 if(i & 1)
235 MD5_Update(&ctx1,final,16);
236 else
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;
249 *p = '\0';
251 /* Don't leave anything around in vm they could use. */
252 memset(final,0,sizeof final);
254 return passwd;
256 #endif /* MD5_CRYPT_SUPPORT */
258 #ifndef NOPROTO
260 STATIC int fcrypt_body(DES_LONG *out0, DES_LONG *out1,
261 des_key_schedule ks, DES_LONG Eswap0, DES_LONG Eswap1);
263 #else
265 STATIC int fcrypt_body();
267 #endif
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
303 #ifndef NOPROTO
304 #ifdef PERL5
305 char *des_crypt(const char *buf,const char *salt);
306 #else
307 char *crypt(const char *buf,const char *salt);
308 #endif
309 #else
310 #ifdef PERL5
311 char *des_crypt();
312 #else
313 char *crypt();
314 #endif
315 #endif
317 #ifdef PERL5
318 char *des_crypt(buf,salt)
319 #else
320 char *crypt(buf,salt)
321 #endif
322 const char *buf;
323 const char *salt;
325 static char buff[14];
327 #if MD5_CRYPT_SUPPORT
328 if (!strncmp(salt, "$1$", 3))
329 return crypt_md5(buf, salt);
330 #endif
332 return(des_fcrypt(buf,salt,buff));
336 char *des_fcrypt(buf,salt,ret)
337 const char *buf;
338 const char *salt;
339 char *ret;
341 unsigned int i,j,x,y;
342 DES_LONG Eswap0,Eswap1;
343 DES_LONG out[2],ll;
344 des_cblock key;
345 des_key_schedule ks;
346 unsigned char bb[9];
347 unsigned char *b=bb;
348 unsigned char c,u;
350 /* eay 25/08/92
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;
363 /* EAY
364 r=strlen(buf);
365 r=(r+7)/8;
367 for (i=0; i<8; i++)
369 c= *(buf++);
370 if (!c) break;
371 key[i]=(c<<1);
373 for (; i<8; i++)
374 key[i]=0;
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);
381 y=0;
382 u=0x80;
383 bb[8]=0;
384 for (i=2; i<13; i++)
386 c=0;
387 for (j=0; j<6; j++)
389 c<<=1;
390 if (bb[y] & u) c|=1;
391 u>>=1;
392 if (!u)
394 y++;
395 u=0x80;
398 ret[i]=cov_2char[c];
400 ret[13]='\0';
401 return(ret);
404 STATIC int fcrypt_body(out0, out1, ks, Eswap0, Eswap1)
405 DES_LONG *out0;
406 DES_LONG *out1;
407 des_key_schedule ks;
408 DES_LONG Eswap0;
409 DES_LONG Eswap1;
411 register DES_LONG l,r,t,u;
412 #ifdef DES_PTR
413 register unsigned char *des_SP=(unsigned char *)des_SPtrans;
414 #endif
415 register DES_LONG *s;
416 register int j;
417 register DES_LONG E0,E1;
419 l=0;
420 r=0;
422 s=(DES_LONG *)ks;
423 E0=Eswap0;
424 E1=Eswap1;
426 for (j=0; j<25; j++)
428 #ifdef DES_UNROLL
429 register int i;
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 */
438 #else
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 */
455 #endif
456 t=l;
457 l=r;
458 r=t;
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);
469 *out0=r;
470 *out1=l;
471 return(0);