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 "smb_common.h"
24 #include "smb_signing.h"
26 #include "lib/crypto/gnutls_helpers.h"
27 #include <gnutls/gnutls.h>
28 #include <gnutls/crypto.h>
30 /* Used by the SMB1 signing functions. */
32 struct smb1_signing_state
{
33 /* is signing locally allowed */
36 /* is signing locally desired */
39 /* is signing locally mandatory */
42 /* is signing negotiated by the peer */
45 bool active
; /* Have I ever seen a validly signed packet? */
47 /* mac_key.length > 0 means signing is started */
50 /* the next expected seqnum */
54 void *(*alloc_fn
)(TALLOC_CTX
*mem_ctx
, size_t len
);
55 void (*free_fn
)(TALLOC_CTX
*mem_ctx
, void *ptr
);
58 static void smb1_signing_reset_info(struct smb1_signing_state
*si
)
64 si
->free_fn(si
->mem_ctx
, si
->mac_key
.data
);
66 talloc_free(si
->mac_key
.data
);
68 si
->mac_key
.data
= NULL
;
69 si
->mac_key
.length
= 0;
72 struct smb1_signing_state
*smb1_signing_init_ex(TALLOC_CTX
*mem_ctx
,
76 void *(*alloc_fn
)(TALLOC_CTX
*, size_t),
77 void (*free_fn
)(TALLOC_CTX
*, void *))
79 struct smb1_signing_state
*si
;
82 void *p
= alloc_fn(mem_ctx
, sizeof(struct smb1_signing_state
));
86 memset(p
, 0, sizeof(struct smb1_signing_state
));
87 si
= (struct smb1_signing_state
*)p
;
88 si
->mem_ctx
= mem_ctx
;
89 si
->alloc_fn
= alloc_fn
;
90 si
->free_fn
= free_fn
;
92 si
= talloc_zero(mem_ctx
, struct smb1_signing_state
);
106 si
->allowed
= allowed
;
107 si
->desired
= desired
;
108 si
->mandatory
= mandatory
;
113 struct smb1_signing_state
*smb1_signing_init(TALLOC_CTX
*mem_ctx
,
118 return smb1_signing_init_ex(mem_ctx
, allowed
, desired
, mandatory
,
122 static bool smb1_signing_good(struct smb1_signing_state
*si
,
123 bool good
, uint32_t seq
)
132 if (!si
->mandatory
&& !si
->active
) {
133 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
134 DBG_INFO("signing negotiated but not required and peer\n"
135 "isn't sending correct signatures. Turning off.\n");
136 smb1_signing_reset_info(si
);
140 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
141 DBG_ERR("BAD SIG: seq %u\n", (unsigned int)seq
);
145 static NTSTATUS
smb1_signing_md5(const DATA_BLOB
*mac_key
,
146 const uint8_t *hdr
, size_t len
,
148 uint8_t calc_md5_mac
[16])
150 const size_t offset_end_of_sig
= (HDR_SS_FIELD
+ 8);
151 uint8_t sequence_buf
[8];
152 gnutls_hash_hd_t hash_hnd
= NULL
;
156 * Firstly put the sequence number into the first 4 bytes.
157 * and zero out the next 4 bytes.
159 * We do this here, to avoid modifying the packet.
162 DBG_DEBUG("sequence number %u\n", seq_number
);
164 SIVAL(sequence_buf
, 0, seq_number
);
165 SIVAL(sequence_buf
, 4, 0);
168 * Calculate the 16 byte MAC - but don't alter the data in the
171 * This makes for a bit of fussing about, but it's not too bad.
173 rc
= gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
175 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
177 /* Initialise with the key. */
178 rc
= gnutls_hash(hash_hnd
, mac_key
->data
, mac_key
->length
);
180 gnutls_hash_deinit(hash_hnd
, NULL
);
181 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
183 /* Copy in the first bit of the SMB header. */
184 rc
= gnutls_hash(hash_hnd
, hdr
, HDR_SS_FIELD
);
186 gnutls_hash_deinit(hash_hnd
, NULL
);
187 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
189 /* Copy in the sequence number, instead of the signature. */
190 rc
= gnutls_hash(hash_hnd
, sequence_buf
, sizeof(sequence_buf
));
192 gnutls_hash_deinit(hash_hnd
, NULL
);
193 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
195 /* Copy in the rest of the packet in, skipping the signature. */
196 rc
= gnutls_hash(hash_hnd
, hdr
+ offset_end_of_sig
, len
- offset_end_of_sig
);
198 gnutls_hash_deinit(hash_hnd
, NULL
);
199 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HASH_NOT_SUPPORTED
);
202 gnutls_hash_deinit(hash_hnd
, calc_md5_mac
);
207 uint32_t smb1_signing_next_seqnum(struct smb1_signing_state
*si
, bool oneway
)
211 if (si
->mac_key
.length
== 0) {
225 void smb1_signing_cancel_reply(struct smb1_signing_state
*si
, bool oneway
)
227 if (si
->mac_key
.length
== 0) {
238 NTSTATUS
smb1_signing_sign_pdu(struct smb1_signing_state
*si
,
239 uint8_t *outhdr
, size_t len
,
242 uint8_t calc_md5_mac
[16];
246 if (si
->mac_key
.length
== 0) {
247 if (!si
->negotiated
) {
252 /* JRA Paranioa test - we should be able to get rid of this... */
253 if (len
< (HDR_SS_FIELD
+ 8)) {
254 DBG_WARNING("Logic error. "
255 "Can't check signature on short packet! smb_len = %u\n",
260 com
= SVAL(outhdr
, HDR_COM
);
261 flags
= SVAL(outhdr
, HDR_FLG
);
263 if (!(flags
& FLAG_REPLY
)) {
264 uint16_t flags2
= SVAL(outhdr
, HDR_FLG2
);
266 * If this is a request, specify what is
267 * supported or required by the client
269 if (si
->negotiated
&& si
->desired
) {
270 flags2
|= FLAGS2_SMB_SECURITY_SIGNATURES
;
272 if (si
->negotiated
&& si
->mandatory
) {
273 flags2
|= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
;
275 SSVAL(outhdr
, HDR_FLG2
, flags2
);
278 if (si
->mac_key
.length
== 0) {
279 /* I wonder what BSRSPYL stands for - but this is what MS
281 if (com
== SMBsesssetupX
) {
282 memcpy(calc_md5_mac
, "BSRSPYL ", 8);
284 memset(calc_md5_mac
, 0, 8);
289 status
= smb1_signing_md5(&si
->mac_key
,
294 if (!NT_STATUS_IS_OK(status
)) {
299 DBG_DEBUG("sent SMB signature of\n");
300 dump_data(10, calc_md5_mac
, 8);
302 memcpy(&outhdr
[HDR_SS_FIELD
], calc_md5_mac
, 8);
304 /* outhdr[HDR_SS_FIELD+2]=0;
305 Uncomment this to test if the remote server actually verifies signatures...*/
310 bool smb1_signing_check_pdu(struct smb1_signing_state
*si
,
311 const uint8_t *inhdr
, size_t len
,
315 uint8_t calc_md5_mac
[16];
316 const uint8_t *reply_sent_mac
;
319 if (si
->mac_key
.length
== 0) {
323 if (len
< (HDR_SS_FIELD
+ 8)) {
324 DBG_WARNING("Can't check signature "
325 "on short packet! smb_len = %u\n",
330 status
= smb1_signing_md5(&si
->mac_key
,
335 if (!NT_STATUS_IS_OK(status
)) {
336 DBG_ERR("Failed to calculate signing mac: %s\n",
341 reply_sent_mac
= &inhdr
[HDR_SS_FIELD
];
342 good
= mem_equal_const_time(reply_sent_mac
, calc_md5_mac
, 8);
346 const int sign_range
= 5;
348 DBG_INFO("BAD SIG: wanted SMB signature of\n");
349 dump_data(5, calc_md5_mac
, 8);
351 DBG_INFO("BAD SIG: got SMB signature of\n");
352 dump_data(5, reply_sent_mac
, 8);
354 for (i
= -sign_range
; i
< sign_range
; i
++) {
355 smb1_signing_md5(&si
->mac_key
, inhdr
, len
,
356 seqnum
+i
, calc_md5_mac
);
357 if (mem_equal_const_time(reply_sent_mac
, calc_md5_mac
, 8)) {
358 DBG_ERR("out of seq. seq num %u matches. "
359 "We were expecting seq %u\n",
360 (unsigned int)seqnum
+i
,
361 (unsigned int)seqnum
);
366 DBG_DEBUG("seq %u: got good SMB signature of\n",
367 (unsigned int)seqnum
);
368 dump_data(10, reply_sent_mac
, 8);
371 return smb1_signing_good(si
, good
, seqnum
);
374 bool smb1_signing_activate(struct smb1_signing_state
*si
,
375 const DATA_BLOB user_session_key
,
376 const DATA_BLOB response
)
381 if (!user_session_key
.length
) {
385 if (!si
->negotiated
) {
393 if (si
->mac_key
.length
> 0) {
397 smb1_signing_reset_info(si
);
399 len
= response
.length
+ user_session_key
.length
;
401 si
->mac_key
.data
= (uint8_t *)si
->alloc_fn(si
->mem_ctx
, len
);
402 if (si
->mac_key
.data
== NULL
) {
406 si
->mac_key
.data
= (uint8_t *)talloc_size(si
, len
);
407 if (si
->mac_key
.data
== NULL
) {
411 si
->mac_key
.length
= len
;
414 memcpy(&si
->mac_key
.data
[ofs
], user_session_key
.data
, user_session_key
.length
);
416 DBG_DEBUG("user_session_key\n");
417 dump_data(10, user_session_key
.data
, user_session_key
.length
);
419 if (response
.length
) {
420 ofs
= user_session_key
.length
;
421 memcpy(&si
->mac_key
.data
[ofs
], response
.data
, response
.length
);
422 DBG_DEBUG("response_data\n");
423 dump_data(10, response
.data
, response
.length
);
425 DBG_DEBUG("NULL response_data\n");
428 dump_data_pw("smb1_signing_activate: mac key is:\n",
429 si
->mac_key
.data
, si
->mac_key
.length
);
431 /* Initialise the sequence number */
437 bool smb1_signing_is_active(struct smb1_signing_state
*si
)
442 bool smb1_signing_is_desired(struct smb1_signing_state
*si
)
447 bool smb1_signing_is_mandatory(struct smb1_signing_state
*si
)
449 return si
->mandatory
;
452 bool smb1_signing_set_negotiated(struct smb1_signing_state
*si
,
453 bool allowed
, bool mandatory
)
463 if (!si
->allowed
&& mandatory
) {
467 if (si
->mandatory
&& !allowed
) {
472 si
->negotiated
= true;
477 si
->negotiated
= true;
482 si
->negotiated
= false;
486 if (si
->desired
&& allowed
) {
487 si
->negotiated
= true;
491 si
->negotiated
= false;
495 bool smb1_signing_is_negotiated(struct smb1_signing_state
*si
)
497 return si
->negotiated
;
500 NTSTATUS
smb1_key_derivation(const uint8_t *KI
,
505 static const uint8_t SSKeyHash
[256] = {
506 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
507 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
508 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
509 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
510 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
511 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
512 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
513 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
514 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
515 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
516 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
517 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
518 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
519 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
520 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
521 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
522 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
523 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
524 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
525 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
526 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
527 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
528 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
529 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
530 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
531 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
532 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
533 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
534 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
535 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
536 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
537 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
540 /* The callers passing down KI_len of 16 so no need to limit to 64 */
541 rc
= gnutls_hmac_fast(GNUTLS_MAC_MD5
,
548 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);