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