1/*
2 *  Unix SMB/CIFS implementation.
3 *  Version 3.0
4 *  NTLMSSP Signing routines
5 *  Copyright (C) Luke Kenneth Casson Leighton 1996-2001
6 *  Copyright (C) Andrew Bartlett 2003
7 *
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.
12 *
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.
17 *
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 Foundation,
20 *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include "includes.h"
24
25#define CLI_SIGN "session key to client-to-server signing key magic constant"
26#define CLI_SEAL "session key to client-to-server sealing key magic constant"
27#define SRV_SIGN "session key to server-to-client signing key magic constant"
28#define SRV_SEAL "session key to server-to-client sealing key magic constant"
29
30static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len)
31{
32    unsigned char index_i = hash[256];
33    unsigned char index_j = hash[257];
34    int ind;
35
36    for (ind = 0; ind < len; ind++)
37    {
38        unsigned char tc;
39        unsigned char t;
40
41        index_i++;
42        index_j += hash[index_i];
43
44        tc = hash[index_i];
45        hash[index_i] = hash[index_j];
46        hash[index_j] = tc;
47
48        t = hash[index_i] + hash[index_j];
49        data[ind] = data[ind] ^ hash[t];
50    }
51
52    hash[256] = index_i;
53    hash[257] = index_j;
54}
55
56static void calc_hash(unsigned char hash[258], unsigned char *k2, int k2l)
57{
58	unsigned char j = 0;
59	int ind;
60
61	for (ind = 0; ind < 256; ind++)
62	{
63		hash[ind] = (unsigned char)ind;
64	}
65
66	for (ind = 0; ind < 256; ind++)
67	{
68		unsigned char tc;
69
70		j += (hash[ind] + k2[ind%k2l]);
71
72		tc = hash[ind];
73		hash[ind] = hash[j];
74		hash[j] = tc;
75	}
76
77	hash[256] = 0;
78	hash[257] = 0;
79}
80
81static void calc_ntlmv2_hash(unsigned char hash[258], unsigned char digest[16],
82			     DATA_BLOB session_key,
83			     const char *constant)
84{
85	struct MD5Context ctx3;
86
87	/* NOTE:  This code is currently complate fantasy - it's
88	   got more in common with reality than the previous code
89	   (the LM session key is not the right thing to use) but
90	   it still needs work */
91
92	MD5Init(&ctx3);
93	MD5Update(&ctx3, session_key.data, session_key.length);
94	MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)+1);
95	MD5Final(digest, &ctx3);
96
97	calc_hash(hash, digest, 16);
98}
99
100enum ntlmssp_direction {
101	NTLMSSP_SEND,
102	NTLMSSP_RECEIVE
103};
104
105static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
106					      const uchar *data, size_t length,
107					      enum ntlmssp_direction direction,
108					      DATA_BLOB *sig)
109{
110	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
111		HMACMD5Context ctx;
112		uchar seq_num[4];
113		uchar digest[16];
114		SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
115
116		hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
117		hmac_md5_update(seq_num, 4, &ctx);
118		hmac_md5_update(data, length, &ctx);
119		hmac_md5_final(digest, &ctx);
120
121		if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
122			       , ntlmssp_state->ntlmssp_seq_num)) {
123			return NT_STATUS_NO_MEMORY;
124		}
125
126		if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
127			switch (direction) {
128			case NTLMSSP_SEND:
129				NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
130				break;
131			case NTLMSSP_RECEIVE:
132				NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash,  sig->data+4, sig->length-4);
133				break;
134			}
135		}
136	} else {
137		uint32 crc;
138		crc = crc32_calc_buffer((const char *)data, length);
139		if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
140			return NT_STATUS_NO_MEMORY;
141		}
142
143		dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
144			     sizeof(ntlmssp_state->ntlmssp_hash));
145		NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
146	}
147	return NT_STATUS_OK;
148}
149
150NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
151				    const uchar *data, size_t length,
152				    DATA_BLOB *sig)
153{
154	NTSTATUS nt_status;
155	if (!ntlmssp_state->session_key.length) {
156		DEBUG(3, ("NO session key, cannot check sign packet\n"));
157		return NT_STATUS_NO_USER_SESSION_KEY;
158	}
159
160	nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
161
162	/* increment counter on send */
163	ntlmssp_state->ntlmssp_seq_num++;
164	return nt_status;
165}
166
167/**
168 * Check the signature of an incoming packet
169 * @note caller *must* check that the signature is the size it expects
170 *
171 */
172
173NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
174			      const uchar *data, size_t length,
175			      const DATA_BLOB *sig)
176{
177	DATA_BLOB local_sig;
178	NTSTATUS nt_status;
179
180	if (!ntlmssp_state->session_key.length) {
181		DEBUG(3, ("NO session key, cannot check packet signature\n"));
182		return NT_STATUS_NO_USER_SESSION_KEY;
183	}
184
185	if (sig->length < 8) {
186		DEBUG(0, ("NTLMSSP packet check failed due to short signature (%lu bytes)!\n",
187			  (unsigned long)sig->length));
188	}
189
190	nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data,
191						  length, NTLMSSP_RECEIVE, &local_sig);
192
193	if (!NT_STATUS_IS_OK(nt_status)) {
194		DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status)));
195		return nt_status;
196	}
197
198	if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) {
199		DEBUG(5, ("BAD SIG: wanted signature of\n"));
200		dump_data(5, (const char *)local_sig.data, local_sig.length);
201
202		DEBUG(5, ("BAD SIG: got signature of\n"));
203		dump_data(5, (const char *)(sig->data), sig->length);
204
205		DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n"));
206		return NT_STATUS_ACCESS_DENIED;
207	}
208
209	/* increment counter on recieive */
210	ntlmssp_state->ntlmssp_seq_num++;
211
212	return NT_STATUS_OK;
213}
214
215
216/**
217 * Seal data with the NTLMSSP algorithm
218 *
219 */
220
221NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
222			     uchar *data, size_t length,
223			     DATA_BLOB *sig)
224{
225	if (!ntlmssp_state->session_key.length) {
226		DEBUG(3, ("NO session key, cannot seal packet\n"));
227		return NT_STATUS_NO_USER_SESSION_KEY;
228	}
229
230	DEBUG(10,("ntlmssp_seal_data: seal\n"));
231	dump_data_pw("ntlmssp clear data\n", data, length);
232	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
233		HMACMD5Context ctx;
234		char seq_num[4];
235		uchar digest[16];
236		SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
237
238		hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
239		hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
240		hmac_md5_update(data, length, &ctx);
241		hmac_md5_final(digest, &ctx);
242
243		if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
244			       , ntlmssp_state->ntlmssp_seq_num)) {
245			return NT_STATUS_NO_MEMORY;
246		}
247
248		dump_data_pw("ntlmssp client sealing hash:\n",
249			     ntlmssp_state->send_seal_hash,
250			     sizeof(ntlmssp_state->send_seal_hash));
251		NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length);
252		dump_data_pw("ntlmssp client signing hash:\n",
253			     ntlmssp_state->send_sign_hash,
254			     sizeof(ntlmssp_state->send_sign_hash));
255		NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
256	} else {
257		uint32 crc;
258		crc = crc32_calc_buffer((const char *)data, length);
259		if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
260			return NT_STATUS_NO_MEMORY;
261		}
262
263		/* The order of these two operations matters - we must first seal the packet,
264		   then seal the sequence number - this is becouse the ntlmssp_hash is not
265		   constant, but is is rather updated with each iteration */
266
267		dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
268			     sizeof(ntlmssp_state->ntlmssp_hash));
269		NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);
270
271		dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
272			     sizeof(ntlmssp_state->ntlmssp_hash));
273		NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
274	}
275	dump_data_pw("ntlmssp sealed data\n", data, length);
276
277	/* increment counter on send */
278	ntlmssp_state->ntlmssp_seq_num++;
279
280	return NT_STATUS_OK;
281}
282
283/**
284 * Unseal data with the NTLMSSP algorithm
285 *
286 */
287
288NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
289				      uchar *data, size_t length,
290				      DATA_BLOB *sig)
291{
292	if (!ntlmssp_state->session_key.length) {
293		DEBUG(3, ("NO session key, cannot unseal packet\n"));
294		return NT_STATUS_NO_USER_SESSION_KEY;
295	}
296
297	DEBUG(10,("ntlmssp__unseal_data: seal\n"));
298	dump_data_pw("ntlmssp sealed data\n", data, length);
299	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
300		NTLMSSPcalc_ap(ntlmssp_state->recv_seal_hash, data, length);
301	} else {
302		dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
303			     sizeof(ntlmssp_state->ntlmssp_hash));
304		NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);
305	}
306	dump_data_pw("ntlmssp clear data\n", data, length);
307
308	return ntlmssp_check_packet(ntlmssp_state, data, length, sig);
309}
310
311/**
312   Initialise the state for NTLMSSP signing.
313*/
314NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
315{
316	unsigned char p24[24];
317	ZERO_STRUCT(p24);
318
319	DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
320	debug_ntlmssp_flags(ntlmssp_state->neg_flags);
321
322	if (!ntlmssp_state->session_key.length) {
323		DEBUG(3, ("NO session key, cannot intialise signing\n"));
324		return NT_STATUS_NO_USER_SESSION_KEY;
325	}
326
327	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
328	{
329		const char *send_sign_const;
330		const char *send_seal_const;
331		const char *recv_sign_const;
332		const char *recv_seal_const;
333
334		switch (ntlmssp_state->role) {
335		case NTLMSSP_CLIENT:
336			send_sign_const = CLI_SIGN;
337			send_seal_const = CLI_SEAL;
338			recv_sign_const = SRV_SIGN;
339			recv_seal_const = SRV_SEAL;
340			break;
341		case NTLMSSP_SERVER:
342			send_sign_const = SRV_SIGN;
343			send_seal_const = SRV_SEAL;
344			recv_sign_const = CLI_SIGN;
345			recv_seal_const = CLI_SEAL;
346			break;
347		default:
348			send_sign_const = "unknown role";
349			send_seal_const = "unknown role";
350			recv_sign_const = "unknown role";
351			recv_seal_const = "unknown role";
352			break;
353		}
354
355		calc_ntlmv2_hash(ntlmssp_state->send_sign_hash,
356				 ntlmssp_state->send_sign_const,
357				 ntlmssp_state->session_key, send_sign_const);
358		dump_data_pw("NTLMSSP send sign hash:\n",
359			     ntlmssp_state->send_sign_hash,
360			     sizeof(ntlmssp_state->send_sign_hash));
361
362		calc_ntlmv2_hash(ntlmssp_state->send_seal_hash,
363				 ntlmssp_state->send_seal_const,
364				 ntlmssp_state->session_key, send_seal_const);
365		dump_data_pw("NTLMSSP send sesl hash:\n",
366			     ntlmssp_state->send_seal_hash,
367			     sizeof(ntlmssp_state->send_seal_hash));
368
369		calc_ntlmv2_hash(ntlmssp_state->recv_sign_hash,
370				 ntlmssp_state->recv_sign_const,
371				 ntlmssp_state->session_key, recv_sign_const);
372		dump_data_pw("NTLMSSP receive sign hash:\n",
373			     ntlmssp_state->recv_sign_hash,
374			     sizeof(ntlmssp_state->recv_sign_hash));
375
376		calc_ntlmv2_hash(ntlmssp_state->recv_seal_hash,
377				 ntlmssp_state->recv_seal_const,
378				 ntlmssp_state->session_key, recv_seal_const);
379		dump_data_pw("NTLMSSP receive seal hash:\n",
380			     ntlmssp_state->recv_sign_hash,
381			     sizeof(ntlmssp_state->recv_sign_hash));
382
383	}
384	else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
385		if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) {
386			/* can't sign or check signatures yet */
387			DEBUG(5, ("NTLMSSP Sign/Seal - cannot use LM KEY yet\n"));
388			return NT_STATUS_UNSUCCESSFUL;
389		}
390
391		DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n"));
392
393		calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8);
394		dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
395			     sizeof(ntlmssp_state->ntlmssp_hash));
396	} else {
397		if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 16) {
398			/* can't sign or check signatures yet */
399			DEBUG(5, ("NTLMSSP Sign/Seal - cannot use NT KEY yet\n"));
400			return NT_STATUS_UNSUCCESSFUL;
401		}
402
403		DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n"));
404
405		calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16);
406		dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
407			     sizeof(ntlmssp_state->ntlmssp_hash));
408	}
409
410	ntlmssp_state->ntlmssp_seq_num = 0;
411
412	return NT_STATUS_OK;
413}
414