Coverage Report

Created: 2025-12-31 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/libcli/smb2/signing.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   SMB2 Signing Code
5
6
   Copyright (C) Andrew Tridgell <tridge@samba.org> 2008
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 3 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, see <http://www.gnu.org/licenses/>.
20
*/
21
22
#include "includes.h"
23
#include "libcli/raw/libcliraw.h"
24
#include "libcli/smb2/smb2.h"
25
#include "libcli/smb2/smb2_calls.h"
26
27
#include <gnutls/gnutls.h>
28
#include <gnutls/crypto.h>
29
#include "lib/crypto/gnutls_helpers.h"
30
31
/*
32
  sign an outgoing message
33
 */
34
NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key)
35
0
{
36
0
  uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
37
0
  uint64_t session_id;
38
0
  size_t hdr_offset;
39
0
  int rc;
40
41
0
  if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
42
    /* can't sign non-SMB2 messages */
43
0
    return NT_STATUS_OK;
44
0
  }
45
46
0
  hdr_offset = buf->hdr - buf->buffer;
47
48
0
  session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
49
0
  if (session_id == 0) {
50
    /* we don't sign messages with a zero session_id. See
51
       MS-SMB2 3.2.4.1.1 */
52
0
    return NT_STATUS_OK;
53
0
  }
54
55
0
  if (session_key.length == 0) {
56
0
    DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
57
0
       (unsigned)session_key.length));
58
0
    return NT_STATUS_ACCESS_DENIED;
59
0
  }
60
61
0
  memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
62
63
0
  SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
64
65
0
  rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
66
0
            session_key.data,
67
0
            MIN(session_key.length, 16),
68
0
            buf->hdr,
69
0
            buf->size - hdr_offset,
70
0
            digest);
71
0
  if (rc < 0) {
72
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
73
0
  }
74
75
0
  DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
76
77
0
  memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
78
79
0
  return NT_STATUS_OK;
80
0
}
81
82
/*
83
  check an incoming signature
84
 */
85
NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key)
86
0
{
87
0
  uint64_t session_id;
88
0
  uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
89
0
  uint8_t sig[16];
90
0
  size_t hdr_offset;
91
0
  int rc;
92
93
0
  if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
94
    /* can't check non-SMB2 messages */
95
0
    return NT_STATUS_OK;
96
0
  }
97
98
0
  hdr_offset = buf->hdr - buf->buffer;
99
100
0
  session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
101
0
  if (session_id == 0) {
102
    /* don't sign messages with a zero session_id. See
103
       MS-SMB2 3.2.4.1.1 */
104
0
    return NT_STATUS_OK;
105
0
  }
106
107
0
  if (session_key.length == 0) {
108
    /* we don't have the session key yet */
109
0
    return NT_STATUS_OK;
110
0
  }
111
112
0
  memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16);
113
114
0
  memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
115
116
0
  rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
117
0
            session_key.data,
118
0
            MIN(session_key.length, 16),
119
0
            buf->hdr,
120
0
            buf->size - hdr_offset,
121
0
            digest);
122
0
  if (rc < 0) {
123
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
124
0
  }
125
126
0
  memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
127
128
0
  if (!mem_equal_const_time(digest, sig, 16)) {
129
0
    DEBUG(0,("Bad SMB2 signature for message of size %u\n",
130
0
       (unsigned)buf->size-NBT_HDR_SIZE));
131
0
    dump_data(0, sig, 16);
132
0
    dump_data(0, digest, 16);
133
0
    ZERO_ARRAY(digest);
134
0
    return NT_STATUS_ACCESS_DENIED;
135
0
  }
136
0
  ZERO_ARRAY(digest);
137
138
0
  return NT_STATUS_OK;
139
0
}