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 <gnutls/gnutls.h>
24 #include <gnutls/crypto.h>
25 #define SMB2_SIGNING_KEY_GNUTLS_TYPES 1
26 #include "../libcli/smb/smb_common.h"
27 #include "../lib/crypto/crypto.h"
28 #include "lib/util/iov_buf.h"
30 #ifndef HAVE_GNUTLS_AES_CMAC
31 #include "lib/crypto/aes.h"
32 #include "lib/crypto/aes_cmac_128.h"
35 #include "lib/crypto/gnutls_helpers.h"
37 void smb2_signing_derivations_fill_const_stack(struct smb2_signing_derivations
*ds
,
38 enum protocol_types protocol
,
39 const DATA_BLOB preauth_hash
)
41 *ds
= (struct smb2_signing_derivations
) { .signing
= NULL
, };
43 if (protocol
>= PROTOCOL_SMB3_10
) {
44 struct smb2_signing_derivation
*d
= NULL
;
46 SMB_ASSERT(preauth_hash
.length
!= 0);
50 d
->label
= data_blob_string_const_null("SMBSigningKey");
51 d
->context
= preauth_hash
;
53 d
= &ds
->__cipher_c2s
;
55 d
->label
= data_blob_string_const_null("SMBC2SCipherKey");
56 d
->context
= preauth_hash
;
58 d
= &ds
->__cipher_s2c
;
60 d
->label
= data_blob_string_const_null("SMBS2CCipherKey");
61 d
->context
= preauth_hash
;
63 d
= &ds
->__application
;
65 d
->label
= data_blob_string_const_null("SMBAppKey");
66 d
->context
= preauth_hash
;
68 } else if (protocol
>= PROTOCOL_SMB2_24
) {
69 struct smb2_signing_derivation
*d
= NULL
;
73 d
->label
= data_blob_string_const_null("SMB2AESCMAC");
74 d
->context
= data_blob_string_const_null("SmbSign");
76 d
= &ds
->__cipher_c2s
;
78 d
->label
= data_blob_string_const_null("SMB2AESCCM");
79 d
->context
= data_blob_string_const_null("ServerIn ");
81 d
= &ds
->__cipher_s2c
;
83 d
->label
= data_blob_string_const_null("SMB2AESCCM");
84 d
->context
= data_blob_string_const_null("ServerOut");
86 d
= &ds
->__application
;
88 d
->label
= data_blob_string_const_null("SMB2APP");
89 d
->context
= data_blob_string_const_null("SmbRpc");
93 static int smb2_signing_key_destructor(struct smb2_signing_key
*key
)
95 if (key
->hmac_hnd
!= NULL
) {
96 gnutls_hmac_deinit(key
->hmac_hnd
, NULL
);
100 if (key
->cipher_hnd
!= NULL
) {
101 gnutls_aead_cipher_deinit(key
->cipher_hnd
);
102 key
->cipher_hnd
= NULL
;
108 NTSTATUS
smb2_signing_key_copy(TALLOC_CTX
*mem_ctx
,
109 const struct smb2_signing_key
*src
,
110 struct smb2_signing_key
**_dst
)
112 struct smb2_signing_key
*dst
= NULL
;
114 dst
= talloc_zero(mem_ctx
, struct smb2_signing_key
);
116 return NT_STATUS_NO_MEMORY
;
118 talloc_set_destructor(dst
, smb2_signing_key_destructor
);
120 dst
->sign_algo_id
= src
->sign_algo_id
;
121 dst
->cipher_algo_id
= src
->cipher_algo_id
;
123 if (src
->blob
.length
== 0) {
128 dst
->blob
= data_blob_talloc_zero(dst
, src
->blob
.length
);
129 if (dst
->blob
.length
== 0) {
131 return NT_STATUS_NO_MEMORY
;
133 talloc_keep_secret(dst
->blob
.data
);
134 memcpy(dst
->blob
.data
, src
->blob
.data
, dst
->blob
.length
);
140 static NTSTATUS
smb2_signing_key_create(TALLOC_CTX
*mem_ctx
,
141 uint16_t sign_algo_id
,
142 uint16_t cipher_algo_id
,
143 const DATA_BLOB
*master_key
,
144 const struct smb2_signing_derivation
*d
,
145 struct smb2_signing_key
**_key
)
147 struct smb2_signing_key
*key
= NULL
;
148 size_t in_key_length
= 16;
149 size_t out_key_length
= 16;
152 if (sign_algo_id
!= SMB2_SIGNING_INVALID_ALGO
) {
153 SMB_ASSERT(cipher_algo_id
== SMB2_ENCRYPTION_INVALID_ALGO
);
155 if (cipher_algo_id
!= SMB2_ENCRYPTION_INVALID_ALGO
) {
156 SMB_ASSERT(sign_algo_id
== SMB2_SIGNING_INVALID_ALGO
);
159 key
= talloc_zero(mem_ctx
, struct smb2_signing_key
);
161 return NT_STATUS_NO_MEMORY
;
163 talloc_set_destructor(key
, smb2_signing_key_destructor
);
165 key
->sign_algo_id
= sign_algo_id
;
166 key
->cipher_algo_id
= cipher_algo_id
;
168 if (master_key
== NULL
) {
169 SMB_ASSERT(d
== NULL
);
176 * Per default use the full key.
178 in_key_length
= out_key_length
= master_key
->length
;
179 switch (sign_algo_id
) {
180 case SMB2_SIGNING_INVALID_ALGO
:
182 * This means we're processing cipher_algo_id below
185 case SMB2_SIGNING_MD5_SMB1
:
186 SMB_ASSERT(d
== NULL
);
188 case SMB2_SIGNING_HMAC_SHA256
:
189 case SMB2_SIGNING_AES128_CMAC
:
191 * signing keys are padded or truncated to
194 * Even with master_key->length = 0,
195 * we need to use 16 zeros.
197 in_key_length
= out_key_length
= 16;
200 DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id
);
201 return NT_STATUS_HMAC_NOT_SUPPORTED
;
203 switch (cipher_algo_id
) {
204 case SMB2_ENCRYPTION_INVALID_ALGO
:
206 * This means we're processing sign_algo_id above
209 case SMB2_ENCRYPTION_NONE
:
211 * No encryption negotiated.
214 case SMB2_ENCRYPTION_AES128_CCM
:
215 case SMB2_ENCRYPTION_AES128_GCM
:
217 * encryption keys are padded or truncated to
220 if (master_key
->length
== 0) {
221 DBG_ERR("cipher_algo_id[%u] without key\n",
223 return NT_STATUS_NO_USER_SESSION_KEY
;
225 in_key_length
= out_key_length
= 16;
228 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id
);
229 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG
;
232 if (out_key_length
== 0) {
237 key
->blob
= data_blob_talloc_zero(key
, out_key_length
);
238 if (key
->blob
.length
== 0) {
240 return NT_STATUS_NO_MEMORY
;
242 talloc_keep_secret(key
->blob
.data
);
243 memcpy(key
->blob
.data
,
245 MIN(key
->blob
.length
, master_key
->length
));
252 status
= smb2_key_derivation(key
->blob
.data
, in_key_length
,
253 d
->label
.data
, d
->label
.length
,
254 d
->context
.data
, d
->context
.length
,
255 key
->blob
.data
, out_key_length
);
256 if (!NT_STATUS_IS_OK(status
)) {
265 NTSTATUS
smb2_signing_key_sign_create(TALLOC_CTX
*mem_ctx
,
266 uint16_t sign_algo_id
,
267 const DATA_BLOB
*master_key
,
268 const struct smb2_signing_derivation
*d
,
269 struct smb2_signing_key
**_key
)
271 return smb2_signing_key_create(mem_ctx
,
273 SMB2_ENCRYPTION_INVALID_ALGO
,
279 NTSTATUS
smb2_signing_key_cipher_create(TALLOC_CTX
*mem_ctx
,
280 uint16_t cipher_algo_id
,
281 const DATA_BLOB
*master_key
,
282 const struct smb2_signing_derivation
*d
,
283 struct smb2_signing_key
**_key
)
285 return smb2_signing_key_create(mem_ctx
,
286 SMB2_SIGNING_INVALID_ALGO
,
293 bool smb2_signing_key_valid(const struct smb2_signing_key
*key
)
299 if (key
->blob
.length
== 0 || key
->blob
.data
== NULL
) {
306 static NTSTATUS
smb2_signing_calc_signature(struct smb2_signing_key
*signing_key
,
307 uint16_t sign_algo_id
,
308 const struct iovec
*vector
,
310 uint8_t signature
[16])
312 const uint8_t *hdr
= (uint8_t *)vector
[0].iov_base
;
313 static const uint8_t zero_sig
[16] = { 0, };
314 gnutls_mac_algorithm_t hmac_algo
= GNUTLS_MAC_UNKNOWN
;
321 * - (optional) SMB2 BODY DYN
322 * - (optional) PADDING
324 SMB_ASSERT(count
>= 2);
325 SMB_ASSERT(vector
[0].iov_len
== SMB2_HDR_BODY
);
326 SMB_ASSERT(count
<= 4);
328 switch (sign_algo_id
) {
329 case SMB2_SIGNING_AES128_CMAC
:
330 #ifdef HAVE_GNUTLS_AES_CMAC
331 hmac_algo
= GNUTLS_MAC_AES_CMAC_128
;
333 #else /* NOT HAVE_GNUTLS_AES_CMAC */
335 struct aes_cmac_128_context ctx
;
336 uint8_t key
[AES_BLOCK_SIZE
] = {0};
339 signing_key
->blob
.data
,
340 MIN(signing_key
->blob
.length
, 16));
342 aes_cmac_128_init(&ctx
, key
);
343 aes_cmac_128_update(&ctx
, hdr
, SMB2_HDR_SIGNATURE
);
344 aes_cmac_128_update(&ctx
, zero_sig
, 16);
345 for (i
=1; i
< count
; i
++) {
346 aes_cmac_128_update(&ctx
,
347 (const uint8_t *)vector
[i
].iov_base
,
350 aes_cmac_128_final(&ctx
, signature
);
357 case SMB2_SIGNING_HMAC_SHA256
:
358 hmac_algo
= GNUTLS_MAC_SHA256
;
362 return NT_STATUS_HMAC_NOT_SUPPORTED
;
365 if (hmac_algo
!= GNUTLS_MAC_UNKNOWN
) {
366 uint8_t digest
[gnutls_hash_get_len(hmac_algo
)];
367 gnutls_datum_t key
= {
368 .data
= signing_key
->blob
.data
,
369 .size
= MIN(signing_key
->blob
.length
, 16),
373 if (signing_key
->hmac_hnd
== NULL
) {
374 rc
= gnutls_hmac_init(&signing_key
->hmac_hnd
,
379 return gnutls_error_to_ntstatus(rc
,
380 NT_STATUS_HMAC_NOT_SUPPORTED
);
384 rc
= gnutls_hmac(signing_key
->hmac_hnd
, hdr
, SMB2_HDR_SIGNATURE
);
386 return gnutls_error_to_ntstatus(rc
,
387 NT_STATUS_HMAC_NOT_SUPPORTED
);
389 rc
= gnutls_hmac(signing_key
->hmac_hnd
, zero_sig
, 16);
391 return gnutls_error_to_ntstatus(rc
,
392 NT_STATUS_HMAC_NOT_SUPPORTED
);
395 for (i
= 1; i
< count
; i
++) {
396 rc
= gnutls_hmac(signing_key
->hmac_hnd
,
400 return gnutls_error_to_ntstatus(rc
,
401 NT_STATUS_HMAC_NOT_SUPPORTED
);
404 gnutls_hmac_output(signing_key
->hmac_hnd
, digest
);
405 memcpy(signature
, digest
, 16);
410 return NT_STATUS_HMAC_NOT_SUPPORTED
;
413 NTSTATUS
smb2_signing_sign_pdu(struct smb2_signing_key
*signing_key
,
414 struct iovec
*vector
,
417 uint16_t sign_algo_id
;
427 * - (optional) SMB2 BODY DYN
428 * - (optional) PADDING
430 SMB_ASSERT(count
>= 2);
431 SMB_ASSERT(vector
[0].iov_len
== SMB2_HDR_BODY
);
432 SMB_ASSERT(count
<= 4);
434 hdr
= (uint8_t *)vector
[0].iov_base
;
436 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
437 if (session_id
== 0) {
439 * do not sign messages with a zero session_id.
440 * See MS-SMB2 3.2.4.1.1
445 if (!smb2_signing_key_valid(signing_key
)) {
446 DBG_WARNING("No signing key for SMB2 signing\n");
447 return NT_STATUS_ACCESS_DENIED
;
450 memset(hdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
452 SIVAL(hdr
, SMB2_HDR_FLAGS
, IVAL(hdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_SIGNED
);
454 sign_algo_id
= signing_key
->sign_algo_id
;
456 status
= smb2_signing_calc_signature(signing_key
,
461 if (!NT_STATUS_IS_OK(status
)) {
462 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
463 (unsigned)sign_algo_id
, nt_errstr(status
));
467 DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
468 (unsigned)sign_algo_id
));
470 memcpy(hdr
+ SMB2_HDR_SIGNATURE
, res
, 16);
475 NTSTATUS
smb2_signing_check_pdu(struct smb2_signing_key
*signing_key
,
476 const struct iovec
*vector
,
479 uint16_t sign_algo_id
;
490 * - (optional) SMB2 BODY DYN
491 * - (optional) PADDING
493 SMB_ASSERT(count
>= 2);
494 SMB_ASSERT(vector
[0].iov_len
== SMB2_HDR_BODY
);
495 SMB_ASSERT(count
<= 4);
497 hdr
= (const uint8_t *)vector
[0].iov_base
;
499 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
500 if (session_id
== 0) {
502 * do not sign messages with a zero session_id.
503 * See MS-SMB2 3.2.4.1.1
508 if (!smb2_signing_key_valid(signing_key
)) {
509 /* we don't have the session key yet */
513 sig
= hdr
+SMB2_HDR_SIGNATURE
;
515 sign_algo_id
= signing_key
->sign_algo_id
;
517 status
= smb2_signing_calc_signature(signing_key
,
522 if (!NT_STATUS_IS_OK(status
)) {
523 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
524 (unsigned)sign_algo_id
, nt_errstr(status
));
528 if (memcmp_const_time(res
, sig
, 16) != 0) {
529 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
530 (unsigned)sign_algo_id
));
531 dump_data(0, sig
, 16);
532 dump_data(0, res
, 16);
533 return NT_STATUS_ACCESS_DENIED
;
539 NTSTATUS
smb2_key_derivation(const uint8_t *KI
, size_t KI_len
,
540 const uint8_t *Label
, size_t Label_len
,
541 const uint8_t *Context
, size_t Context_len
,
542 uint8_t *KO
, size_t KO_len
)
544 gnutls_hmac_hd_t hmac_hnd
= NULL
;
546 static const uint8_t zero
= 0;
547 const size_t digest_len
= gnutls_hash_get_len(GNUTLS_MAC_SHA256
);
548 uint8_t digest
[digest_len
];
550 uint32_t L
= KO_len
* 8;
553 if (KO_len
> digest_len
) {
554 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len
, digest_len
);
555 return NT_STATUS_INTERNAL_ERROR
;
563 DBG_ERR("KO_len[%zu] not supported\n", KO_len
);
564 return NT_STATUS_INTERNAL_ERROR
;
568 * a simplified version of
569 * "NIST Special Publication 800-108" section 5.1
572 rc
= gnutls_hmac_init(&hmac_hnd
,
577 return gnutls_error_to_ntstatus(rc
,
578 NT_STATUS_HMAC_NOT_SUPPORTED
);
582 rc
= gnutls_hmac(hmac_hnd
, buf
, sizeof(buf
));
584 return gnutls_error_to_ntstatus(rc
,
585 NT_STATUS_HMAC_NOT_SUPPORTED
);
587 rc
= gnutls_hmac(hmac_hnd
, Label
, Label_len
);
589 gnutls_hmac_deinit(hmac_hnd
, NULL
);
590 return gnutls_error_to_ntstatus(rc
,
591 NT_STATUS_HMAC_NOT_SUPPORTED
);
593 rc
= gnutls_hmac(hmac_hnd
, &zero
, 1);
595 gnutls_hmac_deinit(hmac_hnd
, NULL
);
596 return gnutls_error_to_ntstatus(rc
,
597 NT_STATUS_HMAC_NOT_SUPPORTED
);
599 rc
= gnutls_hmac(hmac_hnd
, Context
, Context_len
);
601 gnutls_hmac_deinit(hmac_hnd
, NULL
);
602 return gnutls_error_to_ntstatus(rc
,
603 NT_STATUS_HMAC_NOT_SUPPORTED
);
606 rc
= gnutls_hmac(hmac_hnd
, buf
, sizeof(buf
));
608 gnutls_hmac_deinit(hmac_hnd
, NULL
);
609 return gnutls_error_to_ntstatus(rc
,
610 NT_STATUS_HMAC_NOT_SUPPORTED
);
613 gnutls_hmac_deinit(hmac_hnd
, digest
);
615 memcpy(KO
, digest
, KO_len
);
622 NTSTATUS
smb2_signing_encrypt_pdu(struct smb2_signing_key
*encryption_key
,
623 struct iovec
*vector
,
630 uint32_t iv_size
= 0;
631 uint32_t key_size
= 0;
633 uint8_t _key
[16] = {0};
634 gnutls_cipher_algorithm_t algo
= 0;
641 return NT_STATUS_INVALID_PARAMETER
;
644 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
645 return NT_STATUS_INVALID_PARAMETER
;
648 tf
= (uint8_t *)vector
[0].iov_base
;
650 if (!smb2_signing_key_valid(encryption_key
)) {
651 DBG_WARNING("No encryption key for SMB2 signing\n");
652 return NT_STATUS_ACCESS_DENIED
;
654 cipher_id
= encryption_key
->cipher_algo_id
;
656 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
658 m_total
= iov_buflen(&vector
[1], count
-1);
660 return NT_STATUS_BUFFER_TOO_SMALL
;
663 SSVAL(tf
, SMB2_TF_FLAGS
, SMB2_TF_FLAGS_ENCRYPTED
);
664 SIVAL(tf
, SMB2_TF_MSG_SIZE
, m_total
);
667 case SMB2_ENCRYPTION_AES128_CCM
:
668 algo
= GNUTLS_CIPHER_AES_128_CCM
;
669 iv_size
= SMB2_AES_128_CCM_NONCE_SIZE
;
671 case SMB2_ENCRYPTION_AES128_GCM
:
672 algo
= GNUTLS_CIPHER_AES_128_GCM
;
673 iv_size
= gnutls_cipher_get_iv_size(algo
);
676 return NT_STATUS_INVALID_PARAMETER
;
679 key_size
= gnutls_cipher_get_key_size(algo
);
680 tag_size
= gnutls_cipher_get_tag_size(algo
);
682 if (key_size
> sizeof(_key
)) {
683 return NT_STATUS_BUFFER_TOO_SMALL
;
686 key
= (gnutls_datum_t
) {
692 encryption_key
->blob
.data
,
693 MIN(encryption_key
->blob
.length
, key
.size
));
695 iv
= (gnutls_datum_t
) {
696 .data
= tf
+ SMB2_TF_NONCE
,
700 if (encryption_key
->cipher_hnd
== NULL
) {
701 rc
= gnutls_aead_cipher_init(&encryption_key
->cipher_hnd
,
705 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
710 memset(tf
+ SMB2_TF_NONCE
+ iv_size
,
714 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
716 uint8_t tag
[tag_size
];
717 giovec_t auth_iov
[1];
719 auth_iov
[0] = (giovec_t
) {
720 .iov_base
= tf
+ SMB2_TF_NONCE
,
724 rc
= gnutls_aead_cipher_encryptv2(encryption_key
->cipher_hnd
,
734 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
738 memcpy(tf
+ SMB2_TF_SIGNATURE
, tag
, tag_size
);
740 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
742 size_t ptext_size
= m_total
;
743 uint8_t *ptext
= NULL
;
744 size_t ctext_size
= m_total
+ tag_size
;
745 uint8_t *ctext
= NULL
;
748 TALLOC_CTX
*tmp_ctx
= NULL
;
751 * If we come from python bindings, we don't have a stackframe
752 * around, so use the NULL context.
754 * This is fine as we make sure we free the memory.
756 if (talloc_stackframe_exists()) {
757 tmp_ctx
= talloc_tos();
760 ptext
= talloc_size(tmp_ctx
, ptext_size
);
762 status
= NT_STATUS_NO_MEMORY
;
766 ctext
= talloc_size(tmp_ctx
, ctext_size
);
769 status
= NT_STATUS_NO_MEMORY
;
773 for (i
= 1; i
< count
; i
++) {
778 len
+= vector
[i
].iov_len
;
779 if (len
> ptext_size
) {
782 status
= NT_STATUS_INTERNAL_ERROR
;
787 rc
= gnutls_aead_cipher_encrypt(encryption_key
->cipher_hnd
,
797 if (rc
< 0 || ctext_size
!= m_total
+ tag_size
) {
800 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
805 for (i
= 1; i
< count
; i
++) {
806 memcpy(vector
[i
].iov_base
,
810 len
+= vector
[i
].iov_len
;
813 memcpy(tf
+ SMB2_TF_SIGNATURE
, ctext
+ m_total
, tag_size
);
818 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
820 DBG_INFO("Encrypted SMB2 message\n");
822 status
= NT_STATUS_OK
;
829 NTSTATUS
smb2_signing_decrypt_pdu(struct smb2_signing_key
*decryption_key
,
830 struct iovec
*vector
,
838 uint32_t msg_size
= 0;
839 uint32_t iv_size
= 0;
840 uint32_t key_size
= 0;
842 uint8_t _key
[16] = {0};
843 gnutls_cipher_algorithm_t algo
= 0;
850 return NT_STATUS_INVALID_PARAMETER
;
853 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
854 return NT_STATUS_INVALID_PARAMETER
;
857 tf
= (uint8_t *)vector
[0].iov_base
;
859 if (!smb2_signing_key_valid(decryption_key
)) {
860 DBG_WARNING("No decryption key for SMB2 signing\n");
861 return NT_STATUS_ACCESS_DENIED
;
863 cipher_id
= decryption_key
->cipher_algo_id
;
865 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
867 m_total
= iov_buflen(&vector
[1], count
-1);
869 return NT_STATUS_BUFFER_TOO_SMALL
;
872 flags
= SVAL(tf
, SMB2_TF_FLAGS
);
873 msg_size
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
875 if (flags
!= SMB2_TF_FLAGS_ENCRYPTED
) {
876 return NT_STATUS_ACCESS_DENIED
;
879 if (msg_size
!= m_total
) {
880 return NT_STATUS_INTERNAL_ERROR
;
884 case SMB2_ENCRYPTION_AES128_CCM
:
885 algo
= GNUTLS_CIPHER_AES_128_CCM
;
886 iv_size
= SMB2_AES_128_CCM_NONCE_SIZE
;
888 case SMB2_ENCRYPTION_AES128_GCM
:
889 algo
= GNUTLS_CIPHER_AES_128_GCM
;
890 iv_size
= gnutls_cipher_get_iv_size(algo
);
893 return NT_STATUS_INVALID_PARAMETER
;
896 key_size
= gnutls_cipher_get_key_size(algo
);
897 tag_size
= gnutls_cipher_get_tag_size(algo
);
899 if (key_size
> sizeof(_key
)) {
900 return NT_STATUS_BUFFER_TOO_SMALL
;
903 key
= (gnutls_datum_t
) {
909 decryption_key
->blob
.data
,
910 MIN(decryption_key
->blob
.length
, key
.size
));
912 iv
= (gnutls_datum_t
) {
913 .data
= tf
+ SMB2_TF_NONCE
,
917 if (decryption_key
->cipher_hnd
== NULL
) {
918 rc
= gnutls_aead_cipher_init(&decryption_key
->cipher_hnd
,
922 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
927 /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
928 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
930 giovec_t auth_iov
[1];
932 auth_iov
[0] = (giovec_t
) {
933 .iov_base
= tf
+ SMB2_TF_NONCE
,
937 rc
= gnutls_aead_cipher_decryptv2(decryption_key
->cipher_hnd
,
944 tf
+ SMB2_TF_SIGNATURE
,
947 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
951 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
953 size_t ctext_size
= m_total
+ tag_size
;
954 uint8_t *ctext
= NULL
;
955 size_t ptext_size
= m_total
;
956 uint8_t *ptext
= NULL
;
959 TALLOC_CTX
*tmp_ctx
= NULL
;
962 * If we come from python bindings, we don't have a stackframe
963 * around, so use the NULL context.
965 * This is fine as we make sure we free the memory.
967 if (talloc_stackframe_exists()) {
968 tmp_ctx
= talloc_tos();
971 /* GnuTLS doesn't have a iovec API for decryption yet */
973 ptext
= talloc_size(tmp_ctx
, ptext_size
);
975 status
= NT_STATUS_NO_MEMORY
;
979 ctext
= talloc_size(tmp_ctx
, ctext_size
);
982 status
= NT_STATUS_NO_MEMORY
;
987 for (i
= 1; i
< count
; i
++) {
992 len
+= vector
[i
].iov_len
;
994 if (len
!= m_total
) {
997 status
= NT_STATUS_INTERNAL_ERROR
;
1002 tf
+ SMB2_TF_SIGNATURE
,
1005 /* This function will verify the tag */
1006 rc
= gnutls_aead_cipher_decrypt(decryption_key
->cipher_hnd
,
1016 if (rc
< 0 || ptext_size
!= m_total
) {
1019 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1024 for (i
= 1; i
< count
; i
++) {
1025 memcpy(vector
[i
].iov_base
,
1029 len
+= vector
[i
].iov_len
;
1035 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
1037 DBG_INFO("Decrypted SMB2 message\n");
1039 status
= NT_STATUS_OK
;