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 #include <gnutls/gnutls.h>
28 #include <gnutls/crypto.h>
30 /* Used by the SMB signing functions. */
32 struct smb_signing_state {
33 /* is signing localy allowed */
36 /* is signing localy desired */
39 /* is signing localy 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 smb_signing_reset_info(struct smb_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 smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
76 void *(*alloc_fn)(TALLOC_CTX *, size_t),
77 void (*free_fn)(TALLOC_CTX *, void *))
79 struct smb_signing_state *si;
82 void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
86 memset(p, 0, sizeof(struct smb_signing_state));
87 si = (struct smb_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 smb_signing_state);
106 si->allowed = allowed;
107 si->desired = desired;
108 si->mandatory = mandatory;
113 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
118 return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
122 static bool smb_signing_good(struct smb_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 DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n"
135 "isn't sending correct signatures. Turning off.\n"));
136 smb_signing_reset_info(si);
140 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
141 DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
145 static void smb_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 DEBUG(10,("smb_signing_md5: 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);
177 /* Initialise with the key. */
178 rc = gnutls_hash(hash_hnd, mac_key->data, mac_key->length);
180 gnutls_hash_deinit(hash_hnd, NULL);
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);
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);
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);
202 gnutls_hash_deinit(hash_hnd, calc_md5_mac);
205 uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway)
209 if (si->mac_key.length == 0) {
223 void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway)
225 if (si->mac_key.length == 0) {
236 void smb_signing_sign_pdu(struct smb_signing_state *si,
237 uint8_t *outhdr, size_t len,
240 uint8_t calc_md5_mac[16];
244 if (si->mac_key.length == 0) {
245 if (!si->negotiated) {
250 /* JRA Paranioa test - we should be able to get rid of this... */
251 if (len < (HDR_SS_FIELD + 8)) {
252 DEBUG(1,("smb_signing_sign_pdu: Logic error. "
253 "Can't check signature on short packet! smb_len = %u\n",
258 com = SVAL(outhdr, HDR_COM);
259 flags = SVAL(outhdr, HDR_FLG);
261 if (!(flags & FLAG_REPLY)) {
262 uint16_t flags2 = SVAL(outhdr, HDR_FLG2);
264 * If this is a request, specify what is
265 * supported or required by the client
267 if (si->negotiated && si->desired) {
268 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
270 if (si->negotiated && si->mandatory) {
271 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
273 SSVAL(outhdr, HDR_FLG2, flags2);
276 if (si->mac_key.length == 0) {
277 /* I wonder what BSRSPYL stands for - but this is what MS
279 if (com == SMBsesssetupX) {
280 memcpy(calc_md5_mac, "BSRSPYL ", 8);
282 memset(calc_md5_mac, 0, 8);
285 smb_signing_md5(&si->mac_key, outhdr, len,
286 seqnum, calc_md5_mac);
289 DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
290 dump_data(10, calc_md5_mac, 8);
292 memcpy(&outhdr[HDR_SS_FIELD], calc_md5_mac, 8);
294 /* outhdr[HDR_SS_FIELD+2]=0;
295 Uncomment this to test if the remote server actually verifies signatures...*/
298 bool smb_signing_check_pdu(struct smb_signing_state *si,
299 const uint8_t *inhdr, size_t len,
303 uint8_t calc_md5_mac[16];
304 const uint8_t *reply_sent_mac;
306 if (si->mac_key.length == 0) {
310 if (len < (HDR_SS_FIELD + 8)) {
311 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
312 "on short packet! smb_len = %u\n",
317 smb_signing_md5(&si->mac_key, inhdr, len,
318 seqnum, calc_md5_mac);
320 reply_sent_mac = &inhdr[HDR_SS_FIELD];
321 good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);
325 const int sign_range = 5;
327 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
328 dump_data(5, calc_md5_mac, 8);
330 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
331 dump_data(5, reply_sent_mac, 8);
333 for (i = -sign_range; i < sign_range; i++) {
334 smb_signing_md5(&si->mac_key, inhdr, len,
335 seqnum+i, calc_md5_mac);
336 if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) {
337 DEBUG(0,("smb_signing_check_pdu: "
338 "out of seq. seq num %u matches. "
339 "We were expecting seq %u\n",
340 (unsigned int)seqnum+i,
341 (unsigned int)seqnum));
346 DEBUG(10, ("smb_signing_check_pdu: seq %u: "
347 "got good SMB signature of\n",
348 (unsigned int)seqnum));
349 dump_data(10, reply_sent_mac, 8);
352 return smb_signing_good(si, good, seqnum);
355 bool smb_signing_activate(struct smb_signing_state *si,
356 const DATA_BLOB user_session_key,
357 const DATA_BLOB response)
362 if (!user_session_key.length) {
366 if (!si->negotiated) {
374 if (si->mac_key.length > 0) {
378 smb_signing_reset_info(si);
380 len = response.length + user_session_key.length;
382 si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
383 if (si->mac_key.data == NULL) {
387 si->mac_key.data = (uint8_t *)talloc_size(si, len);
388 if (si->mac_key.data == NULL) {
392 si->mac_key.length = len;
395 memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length);
397 DEBUG(10, ("smb_signing_activate: user_session_key\n"));
398 dump_data(10, user_session_key.data, user_session_key.length);
400 if (response.length) {
401 ofs = user_session_key.length;
402 memcpy(&si->mac_key.data[ofs], response.data, response.length);
403 DEBUG(10, ("smb_signing_activate: response_data\n"));
404 dump_data(10, response.data, response.length);
406 DEBUG(10, ("smb_signing_activate: NULL response_data\n"));
409 dump_data_pw("smb_signing_activate: mac key is:\n",
410 si->mac_key.data, si->mac_key.length);
412 /* Initialise the sequence number */
418 bool smb_signing_is_active(struct smb_signing_state *si)
423 bool smb_signing_is_allowed(struct smb_signing_state *si)
428 bool smb_signing_is_desired(struct smb_signing_state *si)
433 bool smb_signing_is_mandatory(struct smb_signing_state *si)
435 return si->mandatory;
438 bool smb_signing_set_negotiated(struct smb_signing_state *si,
439 bool allowed, bool mandatory)
449 if (!si->allowed && mandatory) {
453 if (si->mandatory && !allowed) {
458 si->negotiated = true;
463 si->negotiated = true;
468 si->negotiated = false;
472 if (si->desired && allowed) {
473 si->negotiated = true;
477 si->negotiated = false;
481 bool smb_signing_is_negotiated(struct smb_signing_state *si)
483 return si->negotiated;
486 void smb_key_derivation(const uint8_t *KI, size_t KI_len,
489 static const uint8_t SSKeyHash[256] = {
490 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
491 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
492 0x72, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x55,
493 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x79, 0x07,
494 0x6e, 0x28, 0x2e, 0x69, 0x88, 0x10, 0xb3, 0xdb,
495 0x01, 0x55, 0x72, 0xfb, 0x74, 0x14, 0xfb, 0xc4,
496 0xc5, 0xaf, 0x3b, 0x41, 0x65, 0x32, 0x17, 0xba,
497 0xa3, 0x29, 0x08, 0xc1, 0xde, 0x16, 0x61, 0x7e,
498 0x66, 0x98, 0xa4, 0x0b, 0xfe, 0x06, 0x83, 0x53,
499 0x4d, 0x05, 0xdf, 0x6d, 0xa7, 0x51, 0x10, 0x73,
500 0xc5, 0x50, 0xdc, 0x5e, 0xf8, 0x21, 0x46, 0xaa,
501 0x96, 0x14, 0x33, 0xd7, 0x52, 0xeb, 0xaf, 0x1f,
502 0xbf, 0x36, 0x6c, 0xfc, 0xb7, 0x1d, 0x21, 0x19,
503 0x81, 0xd0, 0x6b, 0xfa, 0x77, 0xad, 0xbe, 0x18,
504 0x78, 0xcf, 0x10, 0xbd, 0xd8, 0x78, 0xf7, 0xd3,
505 0xc6, 0xdf, 0x43, 0x32, 0x19, 0xd3, 0x9b, 0xa8,
506 0x4d, 0x9e, 0xaa, 0x41, 0xaf, 0xcb, 0xc6, 0xb9,
507 0x34, 0xe7, 0x48, 0x25, 0xd4, 0x88, 0xc4, 0x51,
508 0x60, 0x38, 0xd9, 0x62, 0xe8, 0x8d, 0x5b, 0x83,
509 0x92, 0x7f, 0xb5, 0x0e, 0x1c, 0x2d, 0x06, 0x91,
510 0xc3, 0x75, 0xb3, 0xcc, 0xf8, 0xf7, 0x92, 0x91,
511 0x0b, 0x3d, 0xa1, 0x10, 0x5b, 0xd5, 0x0f, 0xa8,
512 0x3f, 0x5d, 0x13, 0x83, 0x0a, 0x6b, 0x72, 0x93,
513 0x14, 0x59, 0xd5, 0xab, 0xde, 0x26, 0x15, 0x6d,
514 0x60, 0x67, 0x71, 0x06, 0x6e, 0x3d, 0x0d, 0xa7,
515 0xcb, 0x70, 0xe9, 0x08, 0x5c, 0x99, 0xfa, 0x0a,
516 0x5f, 0x3d, 0x44, 0xa3, 0x8b, 0xc0, 0x8d, 0xda,
517 0xe2, 0x68, 0xd0, 0x0d, 0xcd, 0x7f, 0x3d, 0xf8,
518 0x73, 0x7e, 0x35, 0x7f, 0x07, 0x02, 0x0a, 0xb5,
519 0xe9, 0xb7, 0x87, 0xfb, 0xa1, 0xbf, 0xcb, 0x32,
520 0x31, 0x66, 0x09, 0x48, 0x88, 0xcc, 0x18, 0xa3,
521 0xb2, 0x1f, 0x1f, 0x1b, 0x90, 0x4e, 0xd7, 0xe1
525 hmac_md5_init_limK_to_64(KI, KI_len, &ctx);
526 hmac_md5_update(SSKeyHash, sizeof(SSKeyHash), &ctx);
527 hmac_md5_final(KO, &ctx);