Annotation of embedaddon/rsync/lib/mdfour.c, revision 1.1
1.1 ! misho 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-2008 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 3 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, visit the http://fsf.org website.
! 21: */
! 22:
! 23: #include "rsync.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: static md_context *m;
! 30:
! 31: #define MASK32 (0xffffffff)
! 32:
! 33: #define F(X,Y,Z) ((((X)&(Y)) | ((~(X))&(Z))))
! 34: #define G(X,Y,Z) ((((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))))
! 35: #define H(X,Y,Z) (((X)^(Y)^(Z)))
! 36: #define lshift(x,s) (((((x)<<(s))&MASK32) | (((x)>>(32-(s)))&MASK32)))
! 37:
! 38: #define ROUND1(a,b,c,d,k,s) a = lshift((a + F(b,c,d) + M[k])&MASK32, s)
! 39: #define ROUND2(a,b,c,d,k,s) a = lshift((a + G(b,c,d) + M[k] + 0x5A827999)&MASK32,s)
! 40: #define ROUND3(a,b,c,d,k,s) a = lshift((a + H(b,c,d) + M[k] + 0x6ED9EBA1)&MASK32,s)
! 41:
! 42: /* this applies md4 to 64 byte chunks */
! 43: static void mdfour64(uint32 *M)
! 44: {
! 45: uint32 AA, BB, CC, DD;
! 46: uint32 A,B,C,D;
! 47:
! 48: A = m->A; B = m->B; C = m->C; D = m->D;
! 49: AA = A; BB = B; CC = C; DD = D;
! 50:
! 51: ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
! 52: ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
! 53: ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
! 54: ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
! 55: ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
! 56: ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
! 57: ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
! 58: ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
! 59:
! 60: ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
! 61: ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
! 62: ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
! 63: ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
! 64: ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
! 65: ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
! 66: ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
! 67: ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
! 68:
! 69: ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
! 70: ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
! 71: ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
! 72: ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
! 73: ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
! 74: ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
! 75: ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
! 76: ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
! 77:
! 78: A += AA; B += BB;
! 79: C += CC; D += DD;
! 80:
! 81: A &= MASK32; B &= MASK32;
! 82: C &= MASK32; D &= MASK32;
! 83:
! 84: m->A = A; m->B = B; m->C = C; m->D = D;
! 85: }
! 86:
! 87: static void copy64(uint32 *M, const uchar *in)
! 88: {
! 89: int i;
! 90:
! 91: for (i = 0; i < MD4_DIGEST_LEN; i++) {
! 92: M[i] = (in[i*4+3] << 24) | (in[i*4+2] << 16)
! 93: | (in[i*4+1] << 8) | (in[i*4+0] << 0);
! 94: }
! 95: }
! 96:
! 97: static void copy4(uchar *out,uint32 x)
! 98: {
! 99: out[0] = x&0xFF;
! 100: out[1] = (x>>8)&0xFF;
! 101: out[2] = (x>>16)&0xFF;
! 102: out[3] = (x>>24)&0xFF;
! 103: }
! 104:
! 105: void mdfour_begin(md_context *md)
! 106: {
! 107: md->A = 0x67452301;
! 108: md->B = 0xefcdab89;
! 109: md->C = 0x98badcfe;
! 110: md->D = 0x10325476;
! 111: md->totalN = 0;
! 112: md->totalN2 = 0;
! 113: }
! 114:
! 115: static void mdfour_tail(const uchar *in, uint32 length)
! 116: {
! 117: uchar buf[128];
! 118: uint32 M[16];
! 119: extern int protocol_version;
! 120:
! 121: /*
! 122: * Count total number of bits, modulo 2^64
! 123: */
! 124: m->totalN += length << 3;
! 125: if (m->totalN < (length << 3))
! 126: m->totalN2++;
! 127: m->totalN2 += length >> 29;
! 128:
! 129: memset(buf, 0, 128);
! 130: if (length)
! 131: memcpy(buf, in, length);
! 132: buf[length] = 0x80;
! 133:
! 134: if (length <= 55) {
! 135: copy4(buf+56, m->totalN);
! 136: /*
! 137: * Prior to protocol version 27 only the number of bits
! 138: * modulo 2^32 was included. MD4 requires the number
! 139: * of bits modulo 2^64, which was fixed starting with
! 140: * protocol version 27.
! 141: */
! 142: if (protocol_version >= 27)
! 143: copy4(buf+60, m->totalN2);
! 144: copy64(M, buf);
! 145: mdfour64(M);
! 146: } else {
! 147: copy4(buf+120, m->totalN);
! 148: /*
! 149: * Prior to protocol version 27 only the number of bits
! 150: * modulo 2^32 was included. MD4 requires the number
! 151: * of bits modulo 2^64, which was fixed starting with
! 152: * protocol version 27.
! 153: */
! 154: if (protocol_version >= 27)
! 155: copy4(buf+124, m->totalN2);
! 156: copy64(M, buf);
! 157: mdfour64(M);
! 158: copy64(M, buf+64);
! 159: mdfour64(M);
! 160: }
! 161: }
! 162:
! 163: void mdfour_update(md_context *md, const uchar *in, uint32 length)
! 164: {
! 165: uint32 M[16];
! 166:
! 167: m = md;
! 168:
! 169: if (length == 0)
! 170: mdfour_tail(in, length);
! 171:
! 172: while (length >= 64) {
! 173: copy64(M, in);
! 174: mdfour64(M);
! 175: in += 64;
! 176: length -= 64;
! 177: m->totalN += 64 << 3;
! 178: if (m->totalN < 64 << 3)
! 179: m->totalN2++;
! 180: }
! 181:
! 182: if (length)
! 183: mdfour_tail(in, length);
! 184: }
! 185:
! 186: void mdfour_result(md_context *md, uchar digest[MD4_DIGEST_LEN])
! 187: {
! 188: m = md;
! 189:
! 190: copy4(digest, m->A);
! 191: copy4(digest+4, m->B);
! 192: copy4(digest+8, m->C);
! 193: copy4(digest+12, m->D);
! 194: }
! 195:
! 196: void mdfour(uchar digest[MD4_DIGEST_LEN], uchar *in, int length)
! 197: {
! 198: md_context md;
! 199: mdfour_begin(&md);
! 200: mdfour_update(&md, in, length);
! 201: mdfour_result(&md, digest);
! 202: }
! 203:
! 204: #ifdef TEST_MDFOUR
! 205: int protocol_version = 28;
! 206:
! 207: static void file_checksum1(char *fname)
! 208: {
! 209: int fd, i, was_multiple_of_64 = 1;
! 210: md_context md;
! 211: uchar buf[64*1024], sum[MD4_DIGEST_LEN];
! 212:
! 213: fd = open(fname,O_RDONLY);
! 214: if (fd == -1) {
! 215: perror("fname");
! 216: exit(1);
! 217: }
! 218:
! 219: mdfour_begin(&md);
! 220:
! 221: while (1) {
! 222: int n = read(fd, buf, sizeof buf);
! 223: if (n <= 0)
! 224: break;
! 225: was_multiple_of_64 = !(n % 64);
! 226: mdfour_update(&md, buf, n);
! 227: }
! 228: if (was_multiple_of_64 && protocol_version >= 27)
! 229: mdfour_update(&md, buf, 0);
! 230:
! 231: close(fd);
! 232:
! 233: mdfour_result(&md, sum);
! 234:
! 235: for (i = 0; i < MD4_DIGEST_LEN; i++)
! 236: printf("%02X", sum[i]);
! 237: printf("\n");
! 238: }
! 239:
! 240: int main(int argc, char *argv[])
! 241: {
! 242: while (--argc)
! 243: file_checksum1(*++argv);
! 244: return 0;
! 245: }
! 246: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>