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 #ifndef HAVE_GNUTLS_AES_CMAC
28 #include "lib/crypto/aes.h"
29 #include "lib/crypto/aes_cmac_128.h"
32 #include "lib/crypto/gnutls_helpers.h"
33 #include <gnutls/gnutls.h>
34 #include <gnutls/crypto.h>
36 int smb2_signing_key_destructor(struct smb2_signing_key
*key
)
38 if (key
->hmac_hnd
!= NULL
) {
39 gnutls_hmac_deinit(key
->hmac_hnd
, NULL
);
43 if (key
->cipher_hnd
!= NULL
) {
44 gnutls_aead_cipher_deinit(key
->cipher_hnd
);
45 key
->cipher_hnd
= NULL
;
51 bool smb2_signing_key_valid(const struct smb2_signing_key
*key
)
57 if (key
->blob
.length
== 0 || key
->blob
.data
== NULL
) {
64 NTSTATUS
smb2_signing_sign_pdu(struct smb2_signing_key
*signing_key
,
65 enum protocol_types protocol
,
75 return NT_STATUS_INVALID_PARAMETER
;
78 if (vector
[0].iov_len
!= SMB2_HDR_BODY
) {
79 return NT_STATUS_INVALID_PARAMETER
;
82 hdr
= (uint8_t *)vector
[0].iov_base
;
84 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
85 if (session_id
== 0) {
87 * do not sign messages with a zero session_id.
88 * See MS-SMB2 3.2.4.1.1
93 if (!smb2_signing_key_valid(signing_key
)) {
94 DBG_WARNING("Wrong session key length %zu for SMB2 signing\n",
95 signing_key
->blob
.length
);
96 return NT_STATUS_ACCESS_DENIED
;
99 memset(hdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
101 SIVAL(hdr
, SMB2_HDR_FLAGS
, IVAL(hdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_SIGNED
);
103 if (protocol
>= PROTOCOL_SMB2_24
) {
104 #ifdef HAVE_GNUTLS_AES_CMAC
105 gnutls_datum_t key
= {
106 .data
= signing_key
->blob
.data
,
107 .size
= MIN(signing_key
->blob
.length
, 16),
111 if (signing_key
->hmac_hnd
== NULL
) {
112 rc
= gnutls_hmac_init(&signing_key
->hmac_hnd
,
113 GNUTLS_MAC_AES_CMAC_128
,
117 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
121 for (i
= 0; i
< count
; i
++) {
122 rc
= gnutls_hmac(signing_key
->hmac_hnd
,
126 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
129 gnutls_hmac_output(signing_key
->hmac_hnd
, res
);
130 #else /* NOT HAVE_GNUTLS_AES_CMAC */
131 struct aes_cmac_128_context ctx
;
132 uint8_t key
[AES_BLOCK_SIZE
] = {0};
135 signing_key
->blob
.data
,
136 MIN(signing_key
->blob
.length
, 16));
138 aes_cmac_128_init(&ctx
, key
);
139 for (i
=0; i
< count
; i
++) {
140 aes_cmac_128_update(&ctx
,
141 (const uint8_t *)vector
[i
].iov_base
,
144 aes_cmac_128_final(&ctx
, res
);
147 #endif /* HAVE_GNUTLS_AES_CMAC */
149 uint8_t digest
[gnutls_hmac_get_len(GNUTLS_MAC_SHA256
)];
152 if (signing_key
->hmac_hnd
== NULL
) {
153 rc
= gnutls_hmac_init(&signing_key
->hmac_hnd
,
155 signing_key
->blob
.data
,
156 MIN(signing_key
->blob
.length
, 16));
158 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
162 for (i
= 0; i
< count
; i
++) {
163 rc
= gnutls_hmac(signing_key
->hmac_hnd
,
167 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
170 gnutls_hmac_output(signing_key
->hmac_hnd
, digest
);
171 memcpy(res
, digest
, sizeof(res
));
173 DEBUG(5,("signed SMB2 message\n"));
175 memcpy(hdr
+ SMB2_HDR_SIGNATURE
, res
, 16);
180 NTSTATUS
smb2_signing_check_pdu(struct smb2_signing_key
*signing_key
,
181 enum protocol_types protocol
,
182 const struct iovec
*vector
,
189 static const uint8_t zero_sig
[16] = { 0, };
193 return NT_STATUS_INVALID_PARAMETER
;
196 if (vector
[0].iov_len
!= SMB2_HDR_BODY
) {
197 return NT_STATUS_INVALID_PARAMETER
;
200 hdr
= (const uint8_t *)vector
[0].iov_base
;
202 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
203 if (session_id
== 0) {
205 * do not sign messages with a zero session_id.
206 * See MS-SMB2 3.2.4.1.1
211 if (!smb2_signing_key_valid(signing_key
)) {
212 /* we don't have the session key yet */
216 sig
= hdr
+SMB2_HDR_SIGNATURE
;
218 if (protocol
>= PROTOCOL_SMB2_24
) {
219 #ifdef HAVE_GNUTLS_AES_CMAC
220 gnutls_datum_t key
= {
221 .data
= signing_key
->blob
.data
,
222 .size
= MIN(signing_key
->blob
.length
, 16),
226 if (signing_key
->hmac_hnd
== NULL
) {
227 rc
= gnutls_hmac_init(&signing_key
->hmac_hnd
,
228 GNUTLS_MAC_AES_CMAC_128
,
232 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
236 rc
= gnutls_hmac(signing_key
->hmac_hnd
, hdr
, SMB2_HDR_SIGNATURE
);
238 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
241 rc
= gnutls_hmac(signing_key
->hmac_hnd
, zero_sig
, 16);
243 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
246 for (i
= 1; i
< count
; i
++) {
247 rc
= gnutls_hmac(signing_key
->hmac_hnd
,
251 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
254 gnutls_hmac_output(signing_key
->hmac_hnd
, res
);
255 #else /* NOT HAVE_GNUTLS_AES_CMAC */
256 struct aes_cmac_128_context ctx
;
257 uint8_t key
[AES_BLOCK_SIZE
] = {0};
260 signing_key
->blob
.data
,
261 MIN(signing_key
->blob
.length
, 16));
263 aes_cmac_128_init(&ctx
, key
);
264 aes_cmac_128_update(&ctx
, hdr
, SMB2_HDR_SIGNATURE
);
265 aes_cmac_128_update(&ctx
, zero_sig
, 16);
266 for (i
=1; i
< count
; i
++) {
267 aes_cmac_128_update(&ctx
,
268 (const uint8_t *)vector
[i
].iov_base
,
271 aes_cmac_128_final(&ctx
, res
);
276 uint8_t digest
[gnutls_hash_get_len(GNUTLS_MAC_SHA256
)];
279 if (signing_key
->hmac_hnd
== NULL
) {
280 rc
= gnutls_hmac_init(&signing_key
->hmac_hnd
,
282 signing_key
->blob
.data
,
283 MIN(signing_key
->blob
.length
, 16));
285 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
289 rc
= gnutls_hmac(signing_key
->hmac_hnd
, hdr
, SMB2_HDR_SIGNATURE
);
291 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
293 rc
= gnutls_hmac(signing_key
->hmac_hnd
, zero_sig
, 16);
295 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
298 for (i
= 1; i
< count
; i
++) {
299 rc
= gnutls_hmac(signing_key
->hmac_hnd
,
303 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
306 gnutls_hmac_output(signing_key
->hmac_hnd
, digest
);
307 memcpy(res
, digest
, 16);
311 if (memcmp_const_time(res
, sig
, 16) != 0) {
312 DEBUG(0,("Bad SMB2 signature for message\n"));
313 dump_data(0, sig
, 16);
314 dump_data(0, res
, 16);
315 return NT_STATUS_ACCESS_DENIED
;
321 NTSTATUS
smb2_key_derivation(const uint8_t *KI
, size_t KI_len
,
322 const uint8_t *Label
, size_t Label_len
,
323 const uint8_t *Context
, size_t Context_len
,
326 gnutls_hmac_hd_t hmac_hnd
= NULL
;
328 static const uint8_t zero
= 0;
329 uint8_t digest
[gnutls_hash_get_len(GNUTLS_MAC_SHA256
)];
335 * a simplified version of
336 * "NIST Special Publication 800-108" section 5.1
339 rc
= gnutls_hmac_init(&hmac_hnd
,
344 return gnutls_error_to_ntstatus(rc
,
345 NT_STATUS_HMAC_NOT_SUPPORTED
);
349 rc
= gnutls_hmac(hmac_hnd
, buf
, sizeof(buf
));
351 return gnutls_error_to_ntstatus(rc
,
352 NT_STATUS_HMAC_NOT_SUPPORTED
);
354 rc
= gnutls_hmac(hmac_hnd
, Label
, Label_len
);
356 gnutls_hmac_deinit(hmac_hnd
, NULL
);
357 return gnutls_error_to_ntstatus(rc
,
358 NT_STATUS_HMAC_NOT_SUPPORTED
);
360 rc
= gnutls_hmac(hmac_hnd
, &zero
, 1);
362 gnutls_hmac_deinit(hmac_hnd
, NULL
);
363 return gnutls_error_to_ntstatus(rc
,
364 NT_STATUS_HMAC_NOT_SUPPORTED
);
366 rc
= gnutls_hmac(hmac_hnd
, Context
, Context_len
);
368 gnutls_hmac_deinit(hmac_hnd
, NULL
);
369 return gnutls_error_to_ntstatus(rc
,
370 NT_STATUS_HMAC_NOT_SUPPORTED
);
373 rc
= gnutls_hmac(hmac_hnd
, buf
, sizeof(buf
));
375 gnutls_hmac_deinit(hmac_hnd
, NULL
);
376 return gnutls_error_to_ntstatus(rc
,
377 NT_STATUS_HMAC_NOT_SUPPORTED
);
380 gnutls_hmac_deinit(hmac_hnd
, digest
);
382 memcpy(KO
, digest
, 16);
389 NTSTATUS
smb2_signing_encrypt_pdu(DATA_BLOB encryption_key
,
391 struct iovec
*vector
,
400 struct aes_ccm_128_context ccm
;
401 struct aes_gcm_128_context gcm
;
403 uint8_t key
[AES_BLOCK_SIZE
];
406 return NT_STATUS_INVALID_PARAMETER
;
409 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
410 return NT_STATUS_INVALID_PARAMETER
;
413 tf
= (uint8_t *)vector
[0].iov_base
;
415 if (encryption_key
.length
== 0) {
416 DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
417 (unsigned)encryption_key
.length
));
418 return NT_STATUS_ACCESS_DENIED
;
421 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
423 m_total
= iov_buflen(&vector
[1], count
-1);
425 return NT_STATUS_BUFFER_TOO_SMALL
;
428 SSVAL(tf
, SMB2_TF_FLAGS
, SMB2_TF_FLAGS_ENCRYPTED
);
429 SIVAL(tf
, SMB2_TF_MSG_SIZE
, m_total
);
432 memcpy(key
, encryption_key
.data
,
433 MIN(encryption_key
.length
, AES_BLOCK_SIZE
));
436 case SMB2_ENCRYPTION_AES128_CCM
:
437 aes_ccm_128_init(&c
.ccm
, key
,
440 memset(tf
+ SMB2_TF_NONCE
+ AES_CCM_128_NONCE_SIZE
, 0,
441 16 - AES_CCM_128_NONCE_SIZE
);
442 aes_ccm_128_update(&c
.ccm
, tf
+ SMB2_TF_NONCE
, a_total
);
443 for (i
=1; i
< count
; i
++) {
444 aes_ccm_128_update(&c
.ccm
,
445 (const uint8_t *)vector
[i
].iov_base
,
447 aes_ccm_128_crypt(&c
.ccm
,
448 (uint8_t *)vector
[i
].iov_base
,
451 aes_ccm_128_digest(&c
.ccm
, sig
);
454 case SMB2_ENCRYPTION_AES128_GCM
:
455 aes_gcm_128_init(&c
.gcm
, key
, tf
+ SMB2_TF_NONCE
);
456 memset(tf
+ SMB2_TF_NONCE
+ AES_GCM_128_IV_SIZE
, 0,
457 16 - AES_GCM_128_IV_SIZE
);
458 aes_gcm_128_updateA(&c
.gcm
, tf
+ SMB2_TF_NONCE
, a_total
);
459 for (i
=1; i
< count
; i
++) {
460 aes_gcm_128_crypt(&c
.gcm
,
461 (uint8_t *)vector
[i
].iov_base
,
463 aes_gcm_128_updateC(&c
.gcm
,
464 (const uint8_t *)vector
[i
].iov_base
,
467 aes_gcm_128_digest(&c
.gcm
, sig
);
472 return NT_STATUS_INVALID_PARAMETER
;
476 memcpy(tf
+ SMB2_TF_SIGNATURE
, sig
, 16);
478 DEBUG(5,("encrypt SMB2 message\n"));
483 NTSTATUS
smb2_signing_decrypt_pdu(DATA_BLOB decryption_key
,
485 struct iovec
*vector
,
490 uint8_t *sig_ptr
= NULL
;
495 uint32_t msg_size
= 0;
497 struct aes_ccm_128_context ccm
;
498 struct aes_gcm_128_context gcm
;
500 uint8_t key
[AES_BLOCK_SIZE
];
503 return NT_STATUS_INVALID_PARAMETER
;
506 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
507 return NT_STATUS_INVALID_PARAMETER
;
510 tf
= (uint8_t *)vector
[0].iov_base
;
512 if (decryption_key
.length
== 0) {
513 DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
514 (unsigned)decryption_key
.length
));
515 return NT_STATUS_ACCESS_DENIED
;
518 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
520 m_total
= iov_buflen(&vector
[1], count
-1);
522 return NT_STATUS_BUFFER_TOO_SMALL
;
525 flags
= SVAL(tf
, SMB2_TF_FLAGS
);
526 msg_size
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
528 if (flags
!= SMB2_TF_FLAGS_ENCRYPTED
) {
529 return NT_STATUS_ACCESS_DENIED
;
532 if (msg_size
!= m_total
) {
533 return NT_STATUS_INTERNAL_ERROR
;
537 memcpy(key
, decryption_key
.data
,
538 MIN(decryption_key
.length
, AES_BLOCK_SIZE
));
541 case SMB2_ENCRYPTION_AES128_CCM
:
542 aes_ccm_128_init(&c
.ccm
, key
,
545 aes_ccm_128_update(&c
.ccm
, tf
+ SMB2_TF_NONCE
, a_total
);
546 for (i
=1; i
< count
; i
++) {
547 aes_ccm_128_crypt(&c
.ccm
,
548 (uint8_t *)vector
[i
].iov_base
,
550 aes_ccm_128_update(&c
.ccm
,
551 ( uint8_t *)vector
[i
].iov_base
,
554 aes_ccm_128_digest(&c
.ccm
, sig
);
557 case SMB2_ENCRYPTION_AES128_GCM
:
558 aes_gcm_128_init(&c
.gcm
, key
, tf
+ SMB2_TF_NONCE
);
559 aes_gcm_128_updateA(&c
.gcm
, tf
+ SMB2_TF_NONCE
, a_total
);
560 for (i
=1; i
< count
; i
++) {
561 aes_gcm_128_updateC(&c
.gcm
,
562 (const uint8_t *)vector
[i
].iov_base
,
564 aes_gcm_128_crypt(&c
.gcm
,
565 (uint8_t *)vector
[i
].iov_base
,
568 aes_gcm_128_digest(&c
.gcm
, sig
);
573 return NT_STATUS_INVALID_PARAMETER
;
577 sig_ptr
= tf
+ SMB2_TF_SIGNATURE
;
578 if (memcmp(sig_ptr
, sig
, 16) != 0) {
579 return NT_STATUS_ACCESS_DENIED
;
582 DEBUG(5,("decrypt SMB2 message\n"));