1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* Copyright (C) 2001-2004 Novell, Inc.
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.
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.
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.
24 #include <glib/gtypes.h>
25 #include "xntlm-md4.h"
29 /* MD4 encoder. The reference implementation in RFC1320 isn't
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))) )
39 md4sum_round (const unsigned char *M,
40 guint32 *AA, guint32 *BB,
41 guint32 *CC, guint32 *DD)
43 guint32 A, B, C, D, X[16];
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);
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);
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);
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);
115 * @in: the input data
116 * @nbytes: the length of @in in bytes
117 * @digest: buffer to compute the digest
119 * Computes the MD4 checksum of @in and puts it in @digest.
122 xntlm_md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
124 unsigned char M[128];
126 int pbytes, nbits = nbytes * 8, remaining_bytes;
127 int total_len, offset;
129 pbytes = (120 - (nbytes % 64)) % 64;
130 total_len = nbytes + pbytes + 8;
137 for (offset = 0; offset < nbytes - 64; offset += 64)
138 md4sum_round (in + offset, &A, &B, &C, &D);
140 /* Copy the leftover part of the message into M */
141 remaining_bytes = nbytes - offset;
142 memcpy (M, in + offset, remaining_bytes);
144 /* Append a single "1" bit and appropriate padding */
145 M[remaining_bytes] = 0x80;
146 memset (M + remaining_bytes + 1, 0, pbytes - 1 + 8);
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 */
155 md4sum_round (M, &A, &B, &C, &D);
156 if (remaining_bytes > 56)
157 md4sum_round (M + 64, &A, &B, &C, &D);
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;