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