2 Unix SMB/CIFS implementation.
4 Copyright (C) Jeremy Allison 2003.
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
6 Copyright (C) Stefan Metzmacher 2009
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 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "../lib/crypto/crypto.h"
24 #include "smb_common.h"
25 #include "smb_signing.h"
27 /* Used by the SMB signing functions. */
29 struct smb_signing_state
{
30 /* is signing localy allowed */
33 /* is signing localy desired */
36 /* is signing localy mandatory */
39 /* is signing negotiated by the peer */
42 bool active
; /* Have I ever seen a validly signed packet? */
44 /* mac_key.length > 0 means signing is started */
47 /* the next expected seqnum */
51 void *(*alloc_fn
)(TALLOC_CTX
*mem_ctx
, size_t len
);
52 void (*free_fn
)(TALLOC_CTX
*mem_ctx
, void *ptr
);
55 static void smb_signing_reset_info(struct smb_signing_state
*si
)
61 si
->free_fn(si
->mem_ctx
, si
->mac_key
.data
);
63 talloc_free(si
->mac_key
.data
);
65 si
->mac_key
.data
= NULL
;
66 si
->mac_key
.length
= 0;
69 struct smb_signing_state
*smb_signing_init_ex(TALLOC_CTX
*mem_ctx
,
73 void *(*alloc_fn
)(TALLOC_CTX
*, size_t),
74 void (*free_fn
)(TALLOC_CTX
*, void *))
76 struct smb_signing_state
*si
;
79 void *p
= alloc_fn(mem_ctx
, sizeof(struct smb_signing_state
));
83 memset(p
, 0, sizeof(struct smb_signing_state
));
84 si
= (struct smb_signing_state
*)p
;
85 si
->mem_ctx
= mem_ctx
;
86 si
->alloc_fn
= alloc_fn
;
87 si
->free_fn
= free_fn
;
89 si
= talloc_zero(mem_ctx
, struct smb_signing_state
);
103 si
->allowed
= allowed
;
104 si
->desired
= desired
;
105 si
->mandatory
= mandatory
;
110 struct smb_signing_state
*smb_signing_init(TALLOC_CTX
*mem_ctx
,
115 return smb_signing_init_ex(mem_ctx
, allowed
, desired
, mandatory
,
119 static bool smb_signing_good(struct smb_signing_state
*si
,
120 bool good
, uint32_t seq
)
129 if (!si
->mandatory
&& !si
->active
) {
130 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
131 DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n"
132 "isn't sending correct signatures. Turning off.\n"));
133 smb_signing_reset_info(si
);
137 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
138 DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq
));
142 static void smb_signing_md5(const DATA_BLOB
*mac_key
,
143 const uint8_t *hdr
, size_t len
,
145 uint8_t calc_md5_mac
[16])
147 const size_t offset_end_of_sig
= (HDR_SS_FIELD
+ 8);
148 uint8_t sequence_buf
[8];
152 * Firstly put the sequence number into the first 4 bytes.
153 * and zero out the next 4 bytes.
155 * We do this here, to avoid modifying the packet.
158 DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number
));
160 SIVAL(sequence_buf
, 0, seq_number
);
161 SIVAL(sequence_buf
, 4, 0);
163 /* Calculate the 16 byte MAC - but don't alter the data in the
166 This makes for a bit of fussing about, but it's not too bad.
170 /* intialise with the key */
171 MD5Update(&md5_ctx
, mac_key
->data
, mac_key
->length
);
173 /* copy in the first bit of the SMB header */
174 MD5Update(&md5_ctx
, hdr
, HDR_SS_FIELD
);
176 /* copy in the sequence number, instead of the signature */
177 MD5Update(&md5_ctx
, sequence_buf
, sizeof(sequence_buf
));
179 /* copy in the rest of the packet in, skipping the signature */
180 MD5Update(&md5_ctx
, hdr
+ offset_end_of_sig
,
181 len
- (offset_end_of_sig
));
183 /* calculate the MD5 sig */
184 MD5Final(calc_md5_mac
, &md5_ctx
);
187 uint32_t smb_signing_next_seqnum(struct smb_signing_state
*si
, bool oneway
)
191 if (si
->mac_key
.length
== 0) {
205 void smb_signing_cancel_reply(struct smb_signing_state
*si
, bool oneway
)
207 if (si
->mac_key
.length
== 0) {
218 void smb_signing_sign_pdu(struct smb_signing_state
*si
,
219 uint8_t *outhdr
, size_t len
,
222 uint8_t calc_md5_mac
[16];
226 if (si
->mac_key
.length
== 0) {
227 if (!si
->negotiated
) {
232 /* JRA Paranioa test - we should be able to get rid of this... */
233 if (len
< (HDR_SS_FIELD
+ 8)) {
234 DEBUG(1,("smb_signing_sign_pdu: Logic error. "
235 "Can't check signature on short packet! smb_len = %u\n",
240 com
= SVAL(outhdr
, HDR_COM
);
241 flags
= SVAL(outhdr
, HDR_FLG
);
243 if (!(flags
& FLAG_REPLY
)) {
244 uint16_t flags2
= SVAL(outhdr
, HDR_FLG2
);
246 * If this is a request, specify what is
247 * supported or required by the client
249 if (si
->negotiated
&& si
->desired
) {
250 flags2
|= FLAGS2_SMB_SECURITY_SIGNATURES
;
252 if (si
->negotiated
&& si
->mandatory
) {
253 flags2
|= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
;
255 SSVAL(outhdr
, HDR_FLG2
, flags2
);
258 if (si
->mac_key
.length
== 0) {
259 /* I wonder what BSRSPYL stands for - but this is what MS
261 if (com
== SMBsesssetupX
) {
262 memcpy(calc_md5_mac
, "BSRSPYL ", 8);
264 memset(calc_md5_mac
, 0, 8);
267 smb_signing_md5(&si
->mac_key
, outhdr
, len
,
268 seqnum
, calc_md5_mac
);
271 DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
272 dump_data(10, calc_md5_mac
, 8);
274 memcpy(&outhdr
[HDR_SS_FIELD
], calc_md5_mac
, 8);
276 /* outhdr[HDR_SS_FIELD+2]=0;
277 Uncomment this to test if the remote server actually verifies signatures...*/
280 bool smb_signing_check_pdu(struct smb_signing_state
*si
,
281 const uint8_t *inhdr
, size_t len
,
285 uint8_t calc_md5_mac
[16];
286 const uint8_t *reply_sent_mac
;
288 if (si
->mac_key
.length
== 0) {
292 if (len
< (HDR_SS_FIELD
+ 8)) {
293 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
294 "on short packet! smb_len = %u\n",
299 smb_signing_md5(&si
->mac_key
, inhdr
, len
,
300 seqnum
, calc_md5_mac
);
302 reply_sent_mac
= &inhdr
[HDR_SS_FIELD
];
303 good
= (memcmp(reply_sent_mac
, calc_md5_mac
, 8) == 0);
307 const int sign_range
= 5;
309 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
310 dump_data(5, calc_md5_mac
, 8);
312 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
313 dump_data(5, reply_sent_mac
, 8);
315 for (i
= -sign_range
; i
< sign_range
; i
++) {
316 smb_signing_md5(&si
->mac_key
, inhdr
, len
,
317 seqnum
+i
, calc_md5_mac
);
318 if (memcmp(reply_sent_mac
, calc_md5_mac
, 8) == 0) {
319 DEBUG(0,("smb_signing_check_pdu: "
320 "out of seq. seq num %u matches. "
321 "We were expecting seq %u\n",
322 (unsigned int)seqnum
+i
,
323 (unsigned int)seqnum
));
328 DEBUG(10, ("smb_signing_check_pdu: seq %u: "
329 "got good SMB signature of\n",
330 (unsigned int)seqnum
));
331 dump_data(10, reply_sent_mac
, 8);
334 return smb_signing_good(si
, good
, seqnum
);
337 bool smb_signing_activate(struct smb_signing_state
*si
,
338 const DATA_BLOB user_session_key
,
339 const DATA_BLOB response
)
344 if (!user_session_key
.length
) {
348 if (!si
->negotiated
) {
356 if (si
->mac_key
.length
> 0) {
360 smb_signing_reset_info(si
);
362 len
= response
.length
+ user_session_key
.length
;
364 si
->mac_key
.data
= (uint8_t *)si
->alloc_fn(si
->mem_ctx
, len
);
365 if (si
->mac_key
.data
== NULL
) {
369 si
->mac_key
.data
= (uint8_t *)talloc_size(si
, len
);
370 if (si
->mac_key
.data
== NULL
) {
374 si
->mac_key
.length
= len
;
377 memcpy(&si
->mac_key
.data
[ofs
], user_session_key
.data
, user_session_key
.length
);
379 DEBUG(10, ("smb_signing_activate: user_session_key\n"));
380 dump_data(10, user_session_key
.data
, user_session_key
.length
);
382 if (response
.length
) {
383 ofs
= user_session_key
.length
;
384 memcpy(&si
->mac_key
.data
[ofs
], response
.data
, response
.length
);
385 DEBUG(10, ("smb_signing_activate: response_data\n"));
386 dump_data(10, response
.data
, response
.length
);
388 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
391 dump_data_pw("smb_signing_activate: mac key is:\n",
392 si
->mac_key
.data
, si
->mac_key
.length
);
394 /* Initialise the sequence number */
400 bool smb_signing_is_active(struct smb_signing_state
*si
)
405 bool smb_signing_is_allowed(struct smb_signing_state
*si
)
410 bool smb_signing_is_desired(struct smb_signing_state
*si
)
415 bool smb_signing_is_mandatory(struct smb_signing_state
*si
)
417 return si
->mandatory
;
420 bool smb_signing_set_negotiated(struct smb_signing_state
*si
,
421 bool allowed
, bool mandatory
)
427 if (!si
->allowed
&& mandatory
) {
431 if (si
->mandatory
&& !allowed
) {
436 si
->negotiated
= true;
441 si
->negotiated
= true;
446 si
->negotiated
= false;
450 if (si
->desired
&& allowed
) {
451 si
->negotiated
= true;
455 si
->negotiated
= false;
459 bool smb_signing_is_negotiated(struct smb_signing_state
*si
)
461 return si
->negotiated
;
464 void smb_key_derivation(const uint8_t *KI
, size_t KI_len
,
467 static const uint8_t SSKeyHash
[256] = {
468 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
469 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
470 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
471 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
472 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
473 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
474 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
475 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
476 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
477 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
478 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
479 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
480 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
481 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
482 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
483 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
484 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
485 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
486 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
487 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
488 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
489 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
490 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
491 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
492 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
493 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
494 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
495 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
496 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
497 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
498 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
499 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
503 hmac_md5_init_limK_to_64(KI
, KI_len
, &ctx
);
504 hmac_md5_update(SSKeyHash
, sizeof(SSKeyHash
), &ctx
);
505 hmac_md5_final(KO
, &ctx
);