Imported Debian patch 0.66.1-1
[hcoop/debian/courier-authlib.git] / libs / md5 / redhat-crypt-md5.c
CommitLineData
d9898ee8 1/*
2** Copyright 1998 - 1999 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#define MD5_INTERNAL
7#include "md5.h"
8#include <string.h>
9
d9898ee8 10
11static char base64[]=
12 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
13
14char *md5_crypt_redhat(const char *pw, const char *salt)
15{
16struct MD5_CONTEXT outer_context, inner_context;
17MD5_DIGEST digest;
18unsigned pwl=strlen(pw);
19unsigned l;
20unsigned i, j;
21char *p;
22static char buffer[100];
23
24 if (*salt == '$' && salt[1] == '1' && salt[2] == '$')
25 salt += 3;
26
27 for (l=0; l<8 && salt[l] && salt[l] != '$'; l++)
28 ;
29
30 md5_context_init(&inner_context);
31 md5_context_hashstream(&inner_context, pw, pwl);
32 md5_context_hashstream(&inner_context, salt, l);
33 md5_context_hashstream(&inner_context, pw, pwl);
34 md5_context_endstream(&inner_context, pwl*2+l);
35 md5_context_digest(&inner_context, digest);
36
37 md5_context_init(&outer_context);
38 md5_context_hashstream(&outer_context, pw, pwl);
39 md5_context_hashstream(&outer_context, "$1$", 3);
40 md5_context_hashstream(&outer_context, salt, l);
41
42 for (i=pwl; i; )
43 {
44 j=i;
45 if (j > 16) j=16;
46 md5_context_hashstream(&outer_context, digest, j);
47 i -= j;
48 }
49
50 j=pwl*2+l+3;
51
52 for (i=pwl; i; i >>= 1)
53 {
54 md5_context_hashstream(&outer_context, (i & 1) ? "": pw, 1);
55 ++j;
56 }
57
58
59 md5_context_endstream(&outer_context, j);
60 md5_context_digest(&outer_context, digest);
61
62 for (i=0; i<1000; i++)
63 {
64 j=0;
65
66 md5_context_init(&outer_context);
67 if (i & 1)
68 {
69 md5_context_hashstream(&outer_context, pw, pwl);
70 j += pwl;
71 }
72 else
73 {
74 md5_context_hashstream(&outer_context, digest, 16);
75 j += 16;
76 }
77
78 if (i % 3)
79 {
80 md5_context_hashstream(&outer_context, salt, l);
81 j += l;
82 }
83
84 if (i % 7)
85 {
86 md5_context_hashstream(&outer_context, pw, pwl);
87 j += pwl;
88 }
89
90 if (i & 1)
91 {
92 md5_context_hashstream(&outer_context, digest, 16);
93 j += 16;
94 }
95 else
96 {
97 md5_context_hashstream(&outer_context, pw, pwl);
98 j += pwl;
99 }
100
101 md5_context_endstream(&outer_context, j);
102 md5_context_digest(&outer_context, digest);
103 }
104
105 strcpy(buffer, "$1$");
106 strncat(buffer, salt, l);
107 strcat(buffer, "$");
108
109 p=buffer+strlen(buffer);
110 for (i=0; i<5; i++)
111 {
112 unsigned char *d=digest;
113
114 j= (d[i] << 16) | (d[i+6] << 8) | d[i == 4 ? 5:12+i];
115 *p++= base64[j & 63] ; j=j >> 6;
116 *p++= base64[j & 63] ; j=j >> 6;
117 *p++= base64[j & 63] ; j=j >> 6;
118 *p++= base64[j & 63];
119 }
120 j=digest[11];
121 *p++ = base64[j & 63]; j=j >> 6;
122 *p++ = base64[j & 63];
123 *p=0;
124 return (buffer);
125}