2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../lib/crypto/crypto.h"
25 #include "lib/util/iov_buf.h"
27 NTSTATUS
smb2_signing_sign_pdu(DATA_BLOB signing_key
,
28 enum protocol_types protocol
,
38 return NT_STATUS_INVALID_PARAMETER
;
41 if (vector
[0].iov_len
!= SMB2_HDR_BODY
) {
42 return NT_STATUS_INVALID_PARAMETER
;
45 hdr
= (uint8_t *)vector
[0].iov_base
;
47 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
48 if (session_id
== 0) {
50 * do not sign messages with a zero session_id.
51 * See MS-SMB2 3.2.4.1.1
56 if (signing_key
.length
== 0) {
57 DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
58 (unsigned)signing_key
.length
));
59 return NT_STATUS_ACCESS_DENIED
;
62 memset(hdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
64 SIVAL(hdr
, SMB2_HDR_FLAGS
, IVAL(hdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_SIGNED
);
66 if (protocol
>= PROTOCOL_SMB2_24
) {
67 struct aes_cmac_128_context ctx
;
68 uint8_t key
[AES_BLOCK_SIZE
] = {0};
70 memcpy(key
, signing_key
.data
, MIN(signing_key
.length
, 16));
72 aes_cmac_128_init(&ctx
, key
);
73 for (i
=0; i
< count
; i
++) {
74 aes_cmac_128_update(&ctx
,
75 (const uint8_t *)vector
[i
].iov_base
,
78 aes_cmac_128_final(&ctx
, res
);
82 struct HMACSHA256Context m
;
83 uint8_t digest
[SHA256_DIGEST_LENGTH
];
86 hmac_sha256_init(signing_key
.data
, MIN(signing_key
.length
, 16), &m
);
87 for (i
=0; i
< count
; i
++) {
88 hmac_sha256_update((const uint8_t *)vector
[i
].iov_base
,
89 vector
[i
].iov_len
, &m
);
91 hmac_sha256_final(digest
, &m
);
92 memcpy(res
, digest
, 16);
94 DEBUG(5,("signed SMB2 message\n"));
96 memcpy(hdr
+ SMB2_HDR_SIGNATURE
, res
, 16);
101 NTSTATUS
smb2_signing_check_pdu(DATA_BLOB signing_key
,
102 enum protocol_types protocol
,
103 const struct iovec
*vector
,
110 static const uint8_t zero_sig
[16] = { 0, };
114 return NT_STATUS_INVALID_PARAMETER
;
117 if (vector
[0].iov_len
!= SMB2_HDR_BODY
) {
118 return NT_STATUS_INVALID_PARAMETER
;
121 hdr
= (const uint8_t *)vector
[0].iov_base
;
123 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
124 if (session_id
== 0) {
126 * do not sign messages with a zero session_id.
127 * See MS-SMB2 3.2.4.1.1
132 if (signing_key
.length
== 0) {
133 /* we don't have the session key yet */
137 sig
= hdr
+SMB2_HDR_SIGNATURE
;
139 if (protocol
>= PROTOCOL_SMB2_24
) {
140 struct aes_cmac_128_context ctx
;
141 uint8_t key
[AES_BLOCK_SIZE
] = {0};
143 memcpy(key
, signing_key
.data
, MIN(signing_key
.length
, 16));
145 aes_cmac_128_init(&ctx
, key
);
146 aes_cmac_128_update(&ctx
, hdr
, SMB2_HDR_SIGNATURE
);
147 aes_cmac_128_update(&ctx
, zero_sig
, 16);
148 for (i
=1; i
< count
; i
++) {
149 aes_cmac_128_update(&ctx
,
150 (const uint8_t *)vector
[i
].iov_base
,
153 aes_cmac_128_final(&ctx
, res
);
157 struct HMACSHA256Context m
;
158 uint8_t digest
[SHA256_DIGEST_LENGTH
];
161 hmac_sha256_init(signing_key
.data
, MIN(signing_key
.length
, 16), &m
);
162 hmac_sha256_update(hdr
, SMB2_HDR_SIGNATURE
, &m
);
163 hmac_sha256_update(zero_sig
, 16, &m
);
164 for (i
=1; i
< count
; i
++) {
165 hmac_sha256_update((const uint8_t *)vector
[i
].iov_base
,
166 vector
[i
].iov_len
, &m
);
168 hmac_sha256_final(digest
, &m
);
169 memcpy(res
, digest
, 16);
172 if (memcmp_const_time(res
, sig
, 16) != 0) {
173 DEBUG(0,("Bad SMB2 signature for message\n"));
174 dump_data(0, sig
, 16);
175 dump_data(0, res
, 16);
176 return NT_STATUS_ACCESS_DENIED
;
182 void smb2_key_derivation(const uint8_t *KI
, size_t KI_len
,
183 const uint8_t *Label
, size_t Label_len
,
184 const uint8_t *Context
, size_t Context_len
,
187 struct HMACSHA256Context ctx
;
189 static const uint8_t zero
= 0;
190 uint8_t digest
[SHA256_DIGEST_LENGTH
];
195 * a simplified version of
196 * "NIST Special Publication 800-108" section 5.1
199 hmac_sha256_init(KI
, KI_len
, &ctx
);
202 hmac_sha256_update(buf
, sizeof(buf
), &ctx
);
203 hmac_sha256_update(Label
, Label_len
, &ctx
);
204 hmac_sha256_update(&zero
, 1, &ctx
);
205 hmac_sha256_update(Context
, Context_len
, &ctx
);
207 hmac_sha256_update(buf
, sizeof(buf
), &ctx
);
209 hmac_sha256_final(digest
, &ctx
);
211 memcpy(KO
, digest
, 16);
214 NTSTATUS
smb2_signing_encrypt_pdu(DATA_BLOB encryption_key
,
216 struct iovec
*vector
,
225 struct aes_ccm_128_context ccm
;
226 struct aes_gcm_128_context gcm
;
228 uint8_t key
[AES_BLOCK_SIZE
];
231 return NT_STATUS_INVALID_PARAMETER
;
234 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
235 return NT_STATUS_INVALID_PARAMETER
;
238 tf
= (uint8_t *)vector
[0].iov_base
;
240 if (encryption_key
.length
== 0) {
241 DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
242 (unsigned)encryption_key
.length
));
243 return NT_STATUS_ACCESS_DENIED
;
246 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
248 m_total
= iov_buflen(&vector
[1], count
-1);
250 return NT_STATUS_BUFFER_TOO_SMALL
;
253 SSVAL(tf
, SMB2_TF_FLAGS
, SMB2_TF_FLAGS_ENCRYPTED
);
254 SIVAL(tf
, SMB2_TF_MSG_SIZE
, m_total
);
257 memcpy(key
, encryption_key
.data
,
258 MIN(encryption_key
.length
, AES_BLOCK_SIZE
));
261 case SMB2_ENCRYPTION_AES128_CCM
:
262 aes_ccm_128_init(&c
.ccm
, key
,
265 memset(tf
+ SMB2_TF_NONCE
+ AES_CCM_128_NONCE_SIZE
, 0,
266 16 - AES_CCM_128_NONCE_SIZE
);
267 aes_ccm_128_update(&c
.ccm
, tf
+ SMB2_TF_NONCE
, a_total
);
268 for (i
=1; i
< count
; i
++) {
269 aes_ccm_128_update(&c
.ccm
,
270 (const uint8_t *)vector
[i
].iov_base
,
272 aes_ccm_128_crypt(&c
.ccm
,
273 (uint8_t *)vector
[i
].iov_base
,
276 aes_ccm_128_digest(&c
.ccm
, sig
);
279 case SMB2_ENCRYPTION_AES128_GCM
:
280 aes_gcm_128_init(&c
.gcm
, key
, tf
+ SMB2_TF_NONCE
);
281 memset(tf
+ SMB2_TF_NONCE
+ AES_GCM_128_IV_SIZE
, 0,
282 16 - AES_GCM_128_IV_SIZE
);
283 aes_gcm_128_updateA(&c
.gcm
, tf
+ SMB2_TF_NONCE
, a_total
);
284 for (i
=1; i
< count
; i
++) {
285 aes_gcm_128_crypt(&c
.gcm
,
286 (uint8_t *)vector
[i
].iov_base
,
288 aes_gcm_128_updateC(&c
.gcm
,
289 (const uint8_t *)vector
[i
].iov_base
,
292 aes_gcm_128_digest(&c
.gcm
, sig
);
297 return NT_STATUS_INVALID_PARAMETER
;
301 memcpy(tf
+ SMB2_TF_SIGNATURE
, sig
, 16);
303 DEBUG(5,("encrypt SMB2 message\n"));
308 NTSTATUS
smb2_signing_decrypt_pdu(DATA_BLOB decryption_key
,
310 struct iovec
*vector
,
315 uint8_t *sig_ptr
= NULL
;
320 uint32_t msg_size
= 0;
322 struct aes_ccm_128_context ccm
;
323 struct aes_gcm_128_context gcm
;
325 uint8_t key
[AES_BLOCK_SIZE
];
328 return NT_STATUS_INVALID_PARAMETER
;
331 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
332 return NT_STATUS_INVALID_PARAMETER
;
335 tf
= (uint8_t *)vector
[0].iov_base
;
337 if (decryption_key
.length
== 0) {
338 DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
339 (unsigned)decryption_key
.length
));
340 return NT_STATUS_ACCESS_DENIED
;
343 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
345 m_total
= iov_buflen(&vector
[1], count
-1);
347 return NT_STATUS_BUFFER_TOO_SMALL
;
350 flags
= SVAL(tf
, SMB2_TF_FLAGS
);
351 msg_size
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
353 if (flags
!= SMB2_TF_FLAGS_ENCRYPTED
) {
354 return NT_STATUS_ACCESS_DENIED
;
357 if (msg_size
!= m_total
) {
358 return NT_STATUS_INTERNAL_ERROR
;
362 memcpy(key
, decryption_key
.data
,
363 MIN(decryption_key
.length
, AES_BLOCK_SIZE
));
366 case SMB2_ENCRYPTION_AES128_CCM
:
367 aes_ccm_128_init(&c
.ccm
, key
,
370 aes_ccm_128_update(&c
.ccm
, tf
+ SMB2_TF_NONCE
, a_total
);
371 for (i
=1; i
< count
; i
++) {
372 aes_ccm_128_crypt(&c
.ccm
,
373 (uint8_t *)vector
[i
].iov_base
,
375 aes_ccm_128_update(&c
.ccm
,
376 ( uint8_t *)vector
[i
].iov_base
,
379 aes_ccm_128_digest(&c
.ccm
, sig
);
382 case SMB2_ENCRYPTION_AES128_GCM
:
383 aes_gcm_128_init(&c
.gcm
, key
, tf
+ SMB2_TF_NONCE
);
384 aes_gcm_128_updateA(&c
.gcm
, tf
+ SMB2_TF_NONCE
, a_total
);
385 for (i
=1; i
< count
; i
++) {
386 aes_gcm_128_updateC(&c
.gcm
,
387 (const uint8_t *)vector
[i
].iov_base
,
389 aes_gcm_128_crypt(&c
.gcm
,
390 (uint8_t *)vector
[i
].iov_base
,
393 aes_gcm_128_digest(&c
.gcm
, sig
);
398 return NT_STATUS_INVALID_PARAMETER
;
402 sig_ptr
= tf
+ SMB2_TF_SIGNATURE
;
403 if (memcmp(sig_ptr
, sig
, 16) != 0) {
404 return NT_STATUS_ACCESS_DENIED
;
407 DEBUG(5,("decrypt SMB2 message\n"));