| Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 1 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2 | Unix SMB/Netbios implementation. | 
|  | 3 | Version 1.9. | 
|  | 4 | a implementation of MD4 designed for use in the SMB authentication protocol | 
|  | 5 | Copyright (C) Andrew Tridgell 1997-1998. | 
|  | 6 | Modified by Steve French (sfrench@us.ibm.com) 2002-2003 | 
| Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 7 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8 | This program is free software; you can redistribute it and/or modify | 
|  | 9 | it under the terms of the GNU General Public License as published by | 
|  | 10 | the Free Software Foundation; either version 2 of the License, or | 
|  | 11 | (at your option) any later version. | 
| Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 12 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | This program is distributed in the hope that it will be useful, | 
|  | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 16 | GNU General Public License for more details. | 
| Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 17 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 | You should have received a copy of the GNU General Public License | 
|  | 19 | along with this program; if not, write to the Free Software | 
|  | 20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 21 | */ | 
|  | 22 | #include <linux/module.h> | 
|  | 23 | #include <linux/fs.h> | 
|  | 24 | #include "cifsencrypt.h" | 
|  | 25 |  | 
|  | 26 | /* NOTE: This code makes no attempt to be fast! */ | 
|  | 27 |  | 
|  | 28 | static __u32 | 
|  | 29 | F(__u32 X, __u32 Y, __u32 Z) | 
|  | 30 | { | 
|  | 31 | return (X & Y) | ((~X) & Z); | 
|  | 32 | } | 
|  | 33 |  | 
|  | 34 | static __u32 | 
|  | 35 | G(__u32 X, __u32 Y, __u32 Z) | 
|  | 36 | { | 
|  | 37 | return (X & Y) | (X & Z) | (Y & Z); | 
|  | 38 | } | 
|  | 39 |  | 
|  | 40 | static __u32 | 
|  | 41 | H(__u32 X, __u32 Y, __u32 Z) | 
|  | 42 | { | 
|  | 43 | return X ^ Y ^ Z; | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | static __u32 | 
|  | 47 | lshift(__u32 x, int s) | 
|  | 48 | { | 
|  | 49 | x &= 0xFFFFFFFF; | 
|  | 50 | return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | #define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s) | 
|  | 54 | #define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s) | 
|  | 55 | #define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s) | 
|  | 56 |  | 
|  | 57 | /* this applies md4 to 64 byte chunks */ | 
|  | 58 | static void | 
|  | 59 | mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D) | 
|  | 60 | { | 
|  | 61 | int j; | 
|  | 62 | __u32 AA, BB, CC, DD; | 
|  | 63 | __u32 X[16]; | 
|  | 64 |  | 
|  | 65 |  | 
|  | 66 | for (j = 0; j < 16; j++) | 
|  | 67 | X[j] = M[j]; | 
|  | 68 |  | 
|  | 69 | AA = *A; | 
|  | 70 | BB = *B; | 
|  | 71 | CC = *C; | 
|  | 72 | DD = *D; | 
|  | 73 |  | 
|  | 74 | ROUND1(A, B, C, D, 0, 3); | 
|  | 75 | ROUND1(D, A, B, C, 1, 7); | 
|  | 76 | ROUND1(C, D, A, B, 2, 11); | 
|  | 77 | ROUND1(B, C, D, A, 3, 19); | 
|  | 78 | ROUND1(A, B, C, D, 4, 3); | 
|  | 79 | ROUND1(D, A, B, C, 5, 7); | 
|  | 80 | ROUND1(C, D, A, B, 6, 11); | 
|  | 81 | ROUND1(B, C, D, A, 7, 19); | 
|  | 82 | ROUND1(A, B, C, D, 8, 3); | 
|  | 83 | ROUND1(D, A, B, C, 9, 7); | 
|  | 84 | ROUND1(C, D, A, B, 10, 11); | 
|  | 85 | ROUND1(B, C, D, A, 11, 19); | 
|  | 86 | ROUND1(A, B, C, D, 12, 3); | 
|  | 87 | ROUND1(D, A, B, C, 13, 7); | 
|  | 88 | ROUND1(C, D, A, B, 14, 11); | 
|  | 89 | ROUND1(B, C, D, A, 15, 19); | 
|  | 90 |  | 
|  | 91 | ROUND2(A, B, C, D, 0, 3); | 
|  | 92 | ROUND2(D, A, B, C, 4, 5); | 
|  | 93 | ROUND2(C, D, A, B, 8, 9); | 
|  | 94 | ROUND2(B, C, D, A, 12, 13); | 
|  | 95 | ROUND2(A, B, C, D, 1, 3); | 
|  | 96 | ROUND2(D, A, B, C, 5, 5); | 
|  | 97 | ROUND2(C, D, A, B, 9, 9); | 
|  | 98 | ROUND2(B, C, D, A, 13, 13); | 
|  | 99 | ROUND2(A, B, C, D, 2, 3); | 
|  | 100 | ROUND2(D, A, B, C, 6, 5); | 
|  | 101 | ROUND2(C, D, A, B, 10, 9); | 
|  | 102 | ROUND2(B, C, D, A, 14, 13); | 
|  | 103 | ROUND2(A, B, C, D, 3, 3); | 
|  | 104 | ROUND2(D, A, B, C, 7, 5); | 
|  | 105 | ROUND2(C, D, A, B, 11, 9); | 
|  | 106 | ROUND2(B, C, D, A, 15, 13); | 
|  | 107 |  | 
|  | 108 | ROUND3(A, B, C, D, 0, 3); | 
|  | 109 | ROUND3(D, A, B, C, 8, 9); | 
|  | 110 | ROUND3(C, D, A, B, 4, 11); | 
|  | 111 | ROUND3(B, C, D, A, 12, 15); | 
|  | 112 | ROUND3(A, B, C, D, 2, 3); | 
|  | 113 | ROUND3(D, A, B, C, 10, 9); | 
|  | 114 | ROUND3(C, D, A, B, 6, 11); | 
|  | 115 | ROUND3(B, C, D, A, 14, 15); | 
|  | 116 | ROUND3(A, B, C, D, 1, 3); | 
|  | 117 | ROUND3(D, A, B, C, 9, 9); | 
|  | 118 | ROUND3(C, D, A, B, 5, 11); | 
|  | 119 | ROUND3(B, C, D, A, 13, 15); | 
|  | 120 | ROUND3(A, B, C, D, 3, 3); | 
|  | 121 | ROUND3(D, A, B, C, 11, 9); | 
|  | 122 | ROUND3(C, D, A, B, 7, 11); | 
|  | 123 | ROUND3(B, C, D, A, 15, 15); | 
|  | 124 |  | 
|  | 125 | *A += AA; | 
|  | 126 | *B += BB; | 
|  | 127 | *C += CC; | 
|  | 128 | *D += DD; | 
|  | 129 |  | 
|  | 130 | *A &= 0xFFFFFFFF; | 
|  | 131 | *B &= 0xFFFFFFFF; | 
|  | 132 | *C &= 0xFFFFFFFF; | 
|  | 133 | *D &= 0xFFFFFFFF; | 
|  | 134 |  | 
|  | 135 | for (j = 0; j < 16; j++) | 
|  | 136 | X[j] = 0; | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | static void | 
|  | 140 | copy64(__u32 * M, unsigned char *in) | 
|  | 141 | { | 
|  | 142 | int i; | 
|  | 143 |  | 
|  | 144 | for (i = 0; i < 16; i++) | 
|  | 145 | M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) | | 
|  | 146 | (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0); | 
|  | 147 | } | 
|  | 148 |  | 
|  | 149 | static void | 
|  | 150 | copy4(unsigned char *out, __u32 x) | 
|  | 151 | { | 
|  | 152 | out[0] = x & 0xFF; | 
|  | 153 | out[1] = (x >> 8) & 0xFF; | 
|  | 154 | out[2] = (x >> 16) & 0xFF; | 
|  | 155 | out[3] = (x >> 24) & 0xFF; | 
|  | 156 | } | 
|  | 157 |  | 
|  | 158 | /* produce a md4 message digest from data of length n bytes */ | 
|  | 159 | void | 
|  | 160 | mdfour(unsigned char *out, unsigned char *in, int n) | 
|  | 161 | { | 
|  | 162 | unsigned char buf[128]; | 
|  | 163 | __u32 M[16]; | 
|  | 164 | __u32 b = n * 8; | 
|  | 165 | int i; | 
|  | 166 | __u32 A = 0x67452301; | 
|  | 167 | __u32 B = 0xefcdab89; | 
|  | 168 | __u32 C = 0x98badcfe; | 
|  | 169 | __u32 D = 0x10325476; | 
|  | 170 |  | 
|  | 171 | while (n > 64) { | 
|  | 172 | copy64(M, in); | 
| Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 173 | mdfour64(M, &A, &B, &C, &D); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 174 | in += 64; | 
|  | 175 | n -= 64; | 
|  | 176 | } | 
|  | 177 |  | 
|  | 178 | for (i = 0; i < 128; i++) | 
|  | 179 | buf[i] = 0; | 
|  | 180 | memcpy(buf, in, n); | 
|  | 181 | buf[n] = 0x80; | 
|  | 182 |  | 
|  | 183 | if (n <= 55) { | 
|  | 184 | copy4(buf + 56, b); | 
|  | 185 | copy64(M, buf); | 
|  | 186 | mdfour64(M, &A, &B, &C, &D); | 
|  | 187 | } else { | 
|  | 188 | copy4(buf + 120, b); | 
|  | 189 | copy64(M, buf); | 
|  | 190 | mdfour64(M, &A, &B, &C, &D); | 
|  | 191 | copy64(M, buf + 64); | 
|  | 192 | mdfour64(M, &A, &B, &C, &D); | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | for (i = 0; i < 128; i++) | 
|  | 196 | buf[i] = 0; | 
|  | 197 | copy64(M, buf); | 
|  | 198 |  | 
|  | 199 | copy4(out, A); | 
|  | 200 | copy4(out + 4, B); | 
|  | 201 | copy4(out + 8, C); | 
|  | 202 | copy4(out + 12, D); | 
|  | 203 |  | 
|  | 204 | A = B = C = D = 0; | 
|  | 205 | } |