Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / servers / exchange / xntlm / xntlm-md4.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* Copyright (C) 2001-2004 Novell, Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU Lesser General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <glib/gtypes.h>
25 #include "xntlm-md4.h"
26
27 #include <string.h>
28
29 /* MD4 encoder. The reference implementation in RFC1320 isn't
30  * GPL-compatible.
31  */
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 ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
37
38 static void
39 md4sum_round (const unsigned char *M,
40               guint32 *AA, guint32 *BB,
41               guint32 *CC, guint32 *DD)
42 {
43         guint32 A, B, C, D, X[16];
44         int i;
45
46         for (i = 0; i < 16; i++) {
47                 X[i] =  (M[i*4]) | (M[i*4 + 1] << 8) |
48                         (M[i*4 + 2] << 16) | (M[i*4 + 3] << 24);
49         }
50
51         A = *AA;
52         B = *BB;
53         C = *CC;
54         D = *DD;
55
56         A = ROT (A + F(B, C, D) + X[0], 3);
57         D = ROT (D + F(A, B, C) + X[1], 7);
58         C = ROT (C + F(D, A, B) + X[2], 11);
59         B = ROT (B + F(C, D, A) + X[3], 19);
60         A = ROT (A + F(B, C, D) + X[4], 3);
61         D = ROT (D + F(A, B, C) + X[5], 7);
62         C = ROT (C + F(D, A, B) + X[6], 11);
63         B = ROT (B + F(C, D, A) + X[7], 19);
64         A = ROT (A + F(B, C, D) + X[8], 3);
65         D = ROT (D + F(A, B, C) + X[9], 7);
66         C = ROT (C + F(D, A, B) + X[10], 11);
67         B = ROT (B + F(C, D, A) + X[11], 19);
68         A = ROT (A + F(B, C, D) + X[12], 3);
69         D = ROT (D + F(A, B, C) + X[13], 7);
70         C = ROT (C + F(D, A, B) + X[14], 11);
71         B = ROT (B + F(C, D, A) + X[15], 19);
72
73         A = ROT (A + G(B, C, D) + X[0]  + 0x5A827999, 3);
74         D = ROT (D + G(A, B, C) + X[4]  + 0x5A827999, 5);
75         C = ROT (C + G(D, A, B) + X[8]  + 0x5A827999, 9);
76         B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13);
77         A = ROT (A + G(B, C, D) + X[1]  + 0x5A827999, 3);
78         D = ROT (D + G(A, B, C) + X[5]  + 0x5A827999, 5);
79         C = ROT (C + G(D, A, B) + X[9]  + 0x5A827999, 9);
80         B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13);
81         A = ROT (A + G(B, C, D) + X[2]  + 0x5A827999, 3);
82         D = ROT (D + G(A, B, C) + X[6]  + 0x5A827999, 5);
83         C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9);
84         B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13);
85         A = ROT (A + G(B, C, D) + X[3]  + 0x5A827999, 3);
86         D = ROT (D + G(A, B, C) + X[7]  + 0x5A827999, 5);
87         C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9);
88         B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13);
89
90         A = ROT (A + H(B, C, D) + X[0]  + 0x6ED9EBA1, 3);
91         D = ROT (D + H(A, B, C) + X[8]  + 0x6ED9EBA1, 9);
92         C = ROT (C + H(D, A, B) + X[4]  + 0x6ED9EBA1, 11);
93         B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15);
94         A = ROT (A + H(B, C, D) + X[2]  + 0x6ED9EBA1, 3);
95         D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9);
96         C = ROT (C + H(D, A, B) + X[6]  + 0x6ED9EBA1, 11);
97         B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15);
98         A = ROT (A + H(B, C, D) + X[1]  + 0x6ED9EBA1, 3);
99         D = ROT (D + H(A, B, C) + X[9]  + 0x6ED9EBA1, 9);
100         C = ROT (C + H(D, A, B) + X[5]  + 0x6ED9EBA1, 11);
101         B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15);
102         A = ROT (A + H(B, C, D) + X[3]  + 0x6ED9EBA1, 3);
103         D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9);
104         C = ROT (C + H(D, A, B) + X[7]  + 0x6ED9EBA1, 11);
105         B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15);
106
107         *AA += A;
108         *BB += B;
109         *CC += C;
110         *DD += D;
111 }
112
113 /**
114  * xntlm_md4sum:
115  * @in: the input data
116  * @nbytes: the length of @in in bytes
117  * @digest: buffer to compute the digest
118  *
119  * Computes the MD4 checksum of @in and puts it in @digest.
120  **/
121 void
122 xntlm_md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
123 {
124         unsigned char M[128];
125         guint32 A, B, C, D;
126         int pbytes, nbits = nbytes * 8, remaining_bytes;
127         int total_len, offset;
128
129         pbytes = (120 - (nbytes % 64)) % 64;
130         total_len = nbytes + pbytes + 8;
131
132         A = 0x67452301;
133         B = 0xEFCDAB89;
134         C = 0x98BADCFE;
135         D = 0x10325476;
136
137         for (offset = 0; offset < nbytes - 64; offset += 64)
138                 md4sum_round (in + offset, &A, &B, &C, &D);
139
140         /* Copy the leftover part of the message into M */
141         remaining_bytes = nbytes - offset;
142         memcpy (M, in + offset, remaining_bytes);
143
144         /* Append a single "1" bit and appropriate padding */
145         M[remaining_bytes] = 0x80;
146         memset (M + remaining_bytes + 1, 0, pbytes - 1 + 8);
147
148         /* Append length. */
149         M[remaining_bytes + pbytes] = nbits & 0xFF;
150         M[remaining_bytes + pbytes + 1] = (nbits >> 8) & 0xFF;
151         M[remaining_bytes + pbytes + 2] = (nbits >> 16) & 0xFF;
152         M[remaining_bytes + pbytes + 3] = (nbits >> 24) & 0xFF;
153         /* We assume nbits is less than 2^32 */
154
155         md4sum_round (M, &A, &B, &C, &D);
156         if (remaining_bytes > 56)
157                 md4sum_round (M + 64, &A, &B, &C, &D);
158
159         digest[0]  =  A        & 0xFF;
160         digest[1]  = (A >>  8) & 0xFF;
161         digest[2]  = (A >> 16) & 0xFF;
162         digest[3]  = (A >> 24) & 0xFF;
163         digest[4]  =  B        & 0xFF;
164         digest[5]  = (B >>  8) & 0xFF;
165         digest[6]  = (B >> 16) & 0xFF;
166         digest[7]  = (B >> 24) & 0xFF;
167         digest[8]  =  C        & 0xFF;
168         digest[9]  = (C >>  8) & 0xFF;
169         digest[10] = (C >> 16) & 0xFF;
170         digest[11] = (C >> 24) & 0xFF;
171         digest[12] =  D        & 0xFF;
172         digest[13] = (D >>  8) & 0xFF;
173         digest[14] = (D >> 16) & 0xFF;
174         digest[15] = (D >> 24) & 0xFF;
175 }