]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/smblib/md4.c
Merge form trunk
[thirdparty/squid.git] / lib / smblib / md4.c
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * a implementation of MD4 designed for use in the SMB authentication protocol
5 * Copyright (C) Andrew Tridgell 1997
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <string.h>
23 #include "smblib/md4.h"
24
25 /* NOTE: This code makes no attempt to be fast!
26 *
27 * It assumes that a int is at least 32 bits long
28 */
29
30 typedef unsigned int uint32;
31
32 static uint32 A, B, C, D;
33
34 static uint32
35 F(uint32 X, uint32 Y, uint32 Z)
36 {
37 return (X & Y) | ((~X) & Z);
38 }
39
40 static uint32
41 G(uint32 X, uint32 Y, uint32 Z)
42 {
43 return (X & Y) | (X & Z) | (Y & Z);
44 }
45
46 static uint32
47 H(uint32 X, uint32 Y, uint32 Z)
48 {
49 return X ^ Y ^ Z;
50 }
51
52 static uint32
53 lshift(uint32 x, int s)
54 {
55 x &= 0xFFFFFFFF;
56 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
57 }
58
59 #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
60 #define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
61 #define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
62
63 /* this applies md4 to 64 byte chunks */
64 static void
65 mdfour64(uint32 * M)
66 {
67 int j;
68 uint32 AA, BB, CC, DD;
69 uint32 X[16];
70
71 for (j = 0; j < 16; j++)
72 X[j] = M[j];
73
74 AA = A;
75 BB = B;
76 CC = C;
77 DD = D;
78
79 ROUND1(A, B, C, D, 0, 3);
80 ROUND1(D, A, B, C, 1, 7);
81 ROUND1(C, D, A, B, 2, 11);
82 ROUND1(B, C, D, A, 3, 19);
83 ROUND1(A, B, C, D, 4, 3);
84 ROUND1(D, A, B, C, 5, 7);
85 ROUND1(C, D, A, B, 6, 11);
86 ROUND1(B, C, D, A, 7, 19);
87 ROUND1(A, B, C, D, 8, 3);
88 ROUND1(D, A, B, C, 9, 7);
89 ROUND1(C, D, A, B, 10, 11);
90 ROUND1(B, C, D, A, 11, 19);
91 ROUND1(A, B, C, D, 12, 3);
92 ROUND1(D, A, B, C, 13, 7);
93 ROUND1(C, D, A, B, 14, 11);
94 ROUND1(B, C, D, A, 15, 19);
95
96 ROUND2(A, B, C, D, 0, 3);
97 ROUND2(D, A, B, C, 4, 5);
98 ROUND2(C, D, A, B, 8, 9);
99 ROUND2(B, C, D, A, 12, 13);
100 ROUND2(A, B, C, D, 1, 3);
101 ROUND2(D, A, B, C, 5, 5);
102 ROUND2(C, D, A, B, 9, 9);
103 ROUND2(B, C, D, A, 13, 13);
104 ROUND2(A, B, C, D, 2, 3);
105 ROUND2(D, A, B, C, 6, 5);
106 ROUND2(C, D, A, B, 10, 9);
107 ROUND2(B, C, D, A, 14, 13);
108 ROUND2(A, B, C, D, 3, 3);
109 ROUND2(D, A, B, C, 7, 5);
110 ROUND2(C, D, A, B, 11, 9);
111 ROUND2(B, C, D, A, 15, 13);
112
113 ROUND3(A, B, C, D, 0, 3);
114 ROUND3(D, A, B, C, 8, 9);
115 ROUND3(C, D, A, B, 4, 11);
116 ROUND3(B, C, D, A, 12, 15);
117 ROUND3(A, B, C, D, 2, 3);
118 ROUND3(D, A, B, C, 10, 9);
119 ROUND3(C, D, A, B, 6, 11);
120 ROUND3(B, C, D, A, 14, 15);
121 ROUND3(A, B, C, D, 1, 3);
122 ROUND3(D, A, B, C, 9, 9);
123 ROUND3(C, D, A, B, 5, 11);
124 ROUND3(B, C, D, A, 13, 15);
125 ROUND3(A, B, C, D, 3, 3);
126 ROUND3(D, A, B, C, 11, 9);
127 ROUND3(C, D, A, B, 7, 11);
128 ROUND3(B, C, D, A, 15, 15);
129
130 A += AA;
131 B += BB;
132 C += CC;
133 D += DD;
134
135 A &= 0xFFFFFFFF;
136 B &= 0xFFFFFFFF;
137 C &= 0xFFFFFFFF;
138 D &= 0xFFFFFFFF;
139
140 for (j = 0; j < 16; j++)
141 X[j] = 0;
142 }
143
144 static void
145 copy64(uint32 * M, unsigned char *in)
146 {
147 int i;
148
149 for (i = 0; i < 16; i++)
150 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
151 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
152 }
153
154 static void
155 copy4(unsigned char *out, uint32 x)
156 {
157 out[0] = x & 0xFF;
158 out[1] = (x >> 8) & 0xFF;
159 out[2] = (x >> 16) & 0xFF;
160 out[3] = (x >> 24) & 0xFF;
161 }
162
163 /* produce a md4 message digest from data of length n bytes */
164 void
165 mdfour(unsigned char *out, unsigned char *in, int n)
166 {
167 unsigned char buf[128];
168 uint32 M[16];
169 uint32 b = n * 8;
170 int i;
171
172 A = 0x67452301;
173 B = 0xefcdab89;
174 C = 0x98badcfe;
175 D = 0x10325476;
176
177 while (n > 64) {
178 copy64(M, in);
179 mdfour64(M);
180 in += 64;
181 n -= 64;
182 }
183
184 for (i = 0; i < 128; i++)
185 buf[i] = 0;
186 memcpy(buf, in, n);
187 buf[n] = 0x80;
188
189 if (n <= 55) {
190 copy4(buf + 56, b);
191 copy64(M, buf);
192 mdfour64(M);
193 } else {
194 copy4(buf + 120, b);
195 copy64(M, buf);
196 mdfour64(M);
197 copy64(M, buf + 64);
198 mdfour64(M);
199 }
200
201 for (i = 0; i < 128; i++)
202 buf[i] = 0;
203 copy64(M, buf);
204
205 copy4(out, A);
206 copy4(out + 4, B);
207 copy4(out + 8, C);
208 copy4(out + 12, D);
209
210 A = B = C = D = 0;
211 }