1/* 2 * Unix SMB/Netbios implementation. 3 * Version 1.9. 4 * An implementation of MD4 designed for use in the SMB authentication protocol. 5 * 6 * Copyright (C) 1997-1998 Andrew Tridgell 7 * Copyright (C) 2005 Wayne Davison 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 22 */ 23 24#include "rsync.h" 25 26/* NOTE: This code makes no attempt to be fast! 27 * 28 * It assumes that a int is at least 32 bits long. */ 29 30static struct mdfour *m; 31 32#define MASK32 (0xffffffff) 33 34#define F(X,Y,Z) ((((X)&(Y)) | ((~(X))&(Z)))) 35#define G(X,Y,Z) ((((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)))) 36#define H(X,Y,Z) (((X)^(Y)^(Z))) 37#define lshift(x,s) (((((x)<<(s))&MASK32) | (((x)>>(32-(s)))&MASK32))) 38 39#define ROUND1(a,b,c,d,k,s) a = lshift((a + F(b,c,d) + M[k])&MASK32, s) 40#define ROUND2(a,b,c,d,k,s) a = lshift((a + G(b,c,d) + M[k] + 0x5A827999)&MASK32,s) 41#define ROUND3(a,b,c,d,k,s) a = lshift((a + H(b,c,d) + M[k] + 0x6ED9EBA1)&MASK32,s) 42 43/* this applies md4 to 64 byte chunks */ 44static void mdfour64(uint32 *M) 45{ 46 uint32 AA, BB, CC, DD; 47 uint32 A,B,C,D; 48 49 A = m->A; B = m->B; C = m->C; D = m->D; 50 AA = A; BB = B; CC = C; DD = D; 51 52 ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); 53 ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19); 54 ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); 55 ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19); 56 ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); 57 ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19); 58 ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); 59 ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); 60 61 62 ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); 63 ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13); 64 ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); 65 ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13); 66 ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); 67 ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13); 68 ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); 69 ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13); 70 71 ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); 72 ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15); 73 ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); 74 ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15); 75 ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); 76 ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15); 77 ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); 78 ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15); 79 80 A += AA; B += BB; 81 C += CC; D += DD; 82 83 A &= MASK32; B &= MASK32; 84 C &= MASK32; D &= MASK32; 85 86 m->A = A; m->B = B; m->C = C; m->D = D; 87} 88 89static void copy64(uint32 *M, unsigned char *in) 90{ 91 int i; 92 93 for (i=0;i<16;i++) 94 M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | 95 (in[i*4+1]<<8) | (in[i*4+0]<<0); 96} 97 98static void copy4(unsigned char *out,uint32 x) 99{ 100 out[0] = x&0xFF; 101 out[1] = (x>>8)&0xFF; 102 out[2] = (x>>16)&0xFF; 103 out[3] = (x>>24)&0xFF; 104} 105 106void mdfour_begin(struct mdfour *md) 107{ 108 md->A = 0x67452301; 109 md->B = 0xefcdab89; 110 md->C = 0x98badcfe; 111 md->D = 0x10325476; 112 md->totalN = 0; 113 md->totalN2 = 0; 114} 115 116 117static void mdfour_tail(unsigned char *in, uint32 n) 118{ 119 unsigned char buf[128]; 120 uint32 M[16]; 121 extern int protocol_version; 122 123 /* 124 * Count total number of bits, modulo 2^64 125 */ 126 m->totalN += n << 3; 127 if (m->totalN < (n << 3)) { 128 m->totalN2++; 129 } 130 m->totalN2 += n >> 29; 131 132 memset(buf, 0, 128); 133 if (n) memcpy(buf, in, n); 134 buf[n] = 0x80; 135 136 if (n <= 55) { 137 copy4(buf+56, m->totalN); 138 /* 139 * Prior to protocol version 27 only the number of bits 140 * modulo 2^32 was included. MD4 requires the number 141 * of bits modulo 2^64, which was fixed starting with 142 * protocol version 27. 143 */ 144 if (protocol_version >= 27) { 145 copy4(buf+60, m->totalN2); 146 } 147 copy64(M, buf); 148 mdfour64(M); 149 } else { 150 copy4(buf+120, m->totalN); 151 /* 152 * Prior to protocol version 27 only the number of bits 153 * modulo 2^32 was included. MD4 requires the number 154 * of bits modulo 2^64, which was fixed starting with 155 * protocol version 27. 156 */ 157 if (protocol_version >= 27) { 158 copy4(buf+124, m->totalN2); 159 } 160 copy64(M, buf); 161 mdfour64(M); 162 copy64(M, buf+64); 163 mdfour64(M); 164 } 165} 166 167void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n) 168{ 169 uint32 M[16]; 170 171 m = md; 172 173 if (n == 0) mdfour_tail(in, n); 174 175 while (n >= 64) { 176 copy64(M, in); 177 mdfour64(M); 178 in += 64; 179 n -= 64; 180 m->totalN += 64 << 3; 181 if (m->totalN < 64 << 3) { 182 m->totalN2++; 183 } 184 } 185 186 if (n) mdfour_tail(in, n); 187} 188 189 190void mdfour_result(struct mdfour *md, unsigned char *out) 191{ 192 m = md; 193 194 copy4(out, m->A); 195 copy4(out+4, m->B); 196 copy4(out+8, m->C); 197 copy4(out+12, m->D); 198} 199 200 201void mdfour(unsigned char *out, unsigned char *in, int n) 202{ 203 struct mdfour md; 204 mdfour_begin(&md); 205 mdfour_update(&md, in, n); 206 mdfour_result(&md, out); 207} 208 209#ifdef TEST_MDFOUR 210int protocol_version = 28; 211 212static void file_checksum1(char *fname) 213{ 214 int fd, i, was_multiple_of_64 = 1; 215 struct mdfour md; 216 unsigned char buf[64*1024], sum[16]; 217 218 fd = open(fname,O_RDONLY); 219 if (fd == -1) { 220 perror("fname"); 221 exit(1); 222 } 223 224 mdfour_begin(&md); 225 226 while (1) { 227 int n = read(fd, buf, sizeof(buf)); 228 if (n <= 0) 229 break; 230 was_multiple_of_64 = !(n % 64); 231 mdfour_update(&md, buf, n); 232 } 233 if (was_multiple_of_64 && protocol_version >= 27) 234 mdfour_update(&md, buf, 0); 235 236 close(fd); 237 238 mdfour_result(&md, sum); 239 240 for (i=0;i<16;i++) 241 printf("%02X", sum[i]); 242 printf("\n"); 243} 244 245#if 0 246#include "../md4.h" 247 248static void file_checksum2(char *fname) 249{ 250 int fd, i; 251 MDstruct md; 252 unsigned char buf[64], sum[16]; 253 254 fd = open(fname,O_RDONLY); 255 if (fd == -1) { 256 perror("fname"); 257 exit(1); 258 } 259 260 MDbegin(&md); 261 262 while (1) { 263 int n = read(fd, buf, sizeof(buf)); 264 if (n <= 0) break; 265 MDupdate(&md, buf, n*8); 266 } 267 268 if (!md.done) { 269 MDupdate(&md, buf, 0); 270 } 271 272 close(fd); 273 274 memcpy(sum, md.buffer, 16); 275 276 for (i=0;i<16;i++) 277 printf("%02X", sum[i]); 278 printf("\n"); 279} 280#endif 281 282 int main(int argc, char *argv[]) 283{ 284 file_checksum1(argv[1]); 285#if 0 286 file_checksum2(argv[1]); 287#endif 288 return 0; 289} 290#endif 291