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_mandatory(struct smb_signing_state
*si
)
412 return si
->mandatory
;
415 bool smb_signing_set_negotiated(struct smb_signing_state
*si
,
416 bool allowed
, bool mandatory
)
422 if (!si
->allowed
&& mandatory
) {
426 if (si
->mandatory
&& !allowed
) {
431 si
->negotiated
= true;
436 si
->negotiated
= true;
441 si
->negotiated
= false;
445 if (si
->desired
&& allowed
) {
446 si
->negotiated
= true;
450 si
->negotiated
= false;
454 bool smb_signing_is_negotiated(struct smb_signing_state
*si
)
456 return si
->negotiated
;
459 void smb_key_derivation(const uint8_t *KI
, size_t KI_len
,
462 static const uint8_t SSKeyHash
[256] = {
463 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
464 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
465 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
466 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
467 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
468 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
469 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
470 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
471 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
472 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
473 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
474 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
475 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
476 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
477 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
478 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
479 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
480 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
481 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
482 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
483 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
484 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
485 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
486 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
487 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
488 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
489 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
490 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
491 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
492 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
493 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
494 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
498 hmac_md5_init_limK_to_64(KI
, KI_len
, &ctx
);
499 hmac_md5_update(SSKeyHash
, sizeof(SSKeyHash
), &ctx
);
500 hmac_md5_final(KO
, &ctx
);