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_11
) {
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_SMB3_00
) {
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
:
190 case SMB2_SIGNING_AES128_GMAC
:
192 * signing keys are padded or truncated to
195 * Even with master_key->length = 0,
196 * we need to use 16 zeros.
198 in_key_length
= out_key_length
= 16;
201 DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id
);
202 return NT_STATUS_HMAC_NOT_SUPPORTED
;
204 switch (cipher_algo_id
) {
205 case SMB2_ENCRYPTION_INVALID_ALGO
:
207 * This means we're processing sign_algo_id above
210 case SMB2_ENCRYPTION_NONE
:
212 * No encryption negotiated.
215 case SMB2_ENCRYPTION_AES128_CCM
:
216 case SMB2_ENCRYPTION_AES128_GCM
:
218 * encryption keys are padded or truncated to
221 if (master_key
->length
== 0) {
222 DBG_ERR("cipher_algo_id[%u] without key\n",
224 return NT_STATUS_NO_USER_SESSION_KEY
;
226 in_key_length
= out_key_length
= 16;
228 case SMB2_ENCRYPTION_AES256_CCM
:
229 case SMB2_ENCRYPTION_AES256_GCM
:
231 * AES256 uses the available input and
232 * generated a 32 byte encryption key.
234 if (master_key
->length
== 0) {
235 DBG_ERR("cipher_algo_id[%u] without key\n",
237 return NT_STATUS_NO_USER_SESSION_KEY
;
242 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id
);
243 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG
;
246 if (out_key_length
== 0) {
251 key
->blob
= data_blob_talloc_zero(key
, out_key_length
);
252 if (key
->blob
.length
== 0) {
254 return NT_STATUS_NO_MEMORY
;
256 talloc_keep_secret(key
->blob
.data
);
257 memcpy(key
->blob
.data
,
259 MIN(key
->blob
.length
, master_key
->length
));
266 status
= smb2_key_derivation(key
->blob
.data
, in_key_length
,
267 d
->label
.data
, d
->label
.length
,
268 d
->context
.data
, d
->context
.length
,
269 key
->blob
.data
, out_key_length
);
270 if (!NT_STATUS_IS_OK(status
)) {
279 NTSTATUS
smb2_signing_key_sign_create(TALLOC_CTX
*mem_ctx
,
280 uint16_t sign_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
,
287 SMB2_ENCRYPTION_INVALID_ALGO
,
293 NTSTATUS
smb2_signing_key_cipher_create(TALLOC_CTX
*mem_ctx
,
294 uint16_t cipher_algo_id
,
295 const DATA_BLOB
*master_key
,
296 const struct smb2_signing_derivation
*d
,
297 struct smb2_signing_key
**_key
)
299 return smb2_signing_key_create(mem_ctx
,
300 SMB2_SIGNING_INVALID_ALGO
,
307 bool smb2_signing_key_valid(const struct smb2_signing_key
*key
)
313 if (key
->blob
.length
== 0 || key
->blob
.data
== NULL
) {
320 static NTSTATUS
smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd
,
321 const uint8_t *iv
, size_t iv_size
,
322 const giovec_t
*auth_iov
, uint8_t auth_iovcnt
,
323 uint8_t *tag
, size_t _tag_size
)
325 size_t tag_size
= _tag_size
;
327 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
329 rc
= gnutls_aead_cipher_encryptv2(cipher_hnd
,
331 auth_iov
, auth_iovcnt
,
335 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
339 #else /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
340 TALLOC_CTX
*tmp_ctx
= NULL
;
341 size_t atext_size
= 0;
342 uint8_t *atext
= NULL
;
347 * If we come from python bindings, we don't have a stackframe
348 * around, so use the NULL context.
350 * This is fine as we make sure we free the memory.
352 if (talloc_stackframe_exists()) {
353 tmp_ctx
= talloc_tos();
356 for (i
=0; i
< auth_iovcnt
; i
++) {
357 atext_size
+= auth_iov
[i
].iov_len
;
360 atext
= talloc_size(tmp_ctx
, atext_size
);
362 return NT_STATUS_NO_MEMORY
;
365 for (i
= 0; i
< auth_iovcnt
; i
++) {
367 auth_iov
[i
].iov_base
,
368 auth_iov
[i
].iov_len
);
370 len
+= auth_iov
[i
].iov_len
;
371 if (len
> atext_size
) {
373 return NT_STATUS_INTERNAL_ERROR
;
377 rc
= gnutls_aead_cipher_encrypt(cipher_hnd
,
386 return gnutls_error_to_ntstatus(rc
, NT_STATUS_HMAC_NOT_SUPPORTED
);
390 #endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
393 static NTSTATUS
smb2_signing_calc_signature(struct smb2_signing_key
*signing_key
,
394 uint16_t sign_algo_id
,
395 const struct iovec
*vector
,
397 uint8_t signature
[16])
399 const uint8_t *hdr
= (uint8_t *)vector
[0].iov_base
;
403 static const uint8_t zero_sig
[16] = { 0, };
404 gnutls_mac_algorithm_t hmac_algo
= GNUTLS_MAC_UNKNOWN
;
411 * - (optional) SMB2 BODY DYN
412 * - (optional) PADDING
414 SMB_ASSERT(count
>= 2);
415 SMB_ASSERT(vector
[0].iov_len
== SMB2_HDR_BODY
);
416 SMB_ASSERT(count
<= 4);
418 opcode
= SVAL(hdr
, SMB2_HDR_OPCODE
);
419 flags
= IVAL(hdr
, SMB2_HDR_FLAGS
);
420 if (flags
& SMB2_HDR_FLAG_REDIRECT
) {
421 NTSTATUS pdu_status
= NT_STATUS(IVAL(hdr
, SMB2_HDR_STATUS
));
422 if (NT_STATUS_EQUAL(pdu_status
, NT_STATUS_PENDING
)) {
423 DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode
);
424 return NT_STATUS_INTERNAL_ERROR
;
426 if (opcode
== SMB2_OP_CANCEL
) {
427 DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
428 return NT_STATUS_INTERNAL_ERROR
;
431 msg_id
= BVAL(hdr
, SMB2_HDR_MESSAGE_ID
);
433 if (opcode
!= SMB2_OP_CANCEL
||
434 sign_algo_id
>= SMB2_SIGNING_AES128_GMAC
)
436 DBG_ERR("opcode[%u] msg_id == 0\n", opcode
);
437 return NT_STATUS_INTERNAL_ERROR
;
440 * Legacy algorithms allow MID 0
441 * for cancel requests
444 if (msg_id
== UINT64_MAX
) {
445 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode
);
446 return NT_STATUS_INTERNAL_ERROR
;
449 switch (sign_algo_id
) {
450 case SMB2_SIGNING_AES128_GMAC
: {
451 gnutls_cipher_algorithm_t algo
= GNUTLS_CIPHER_AES_128_GCM
;
452 uint32_t key_size
= gnutls_cipher_get_key_size(algo
);
453 uint32_t iv_size
= gnutls_cipher_get_iv_size(algo
);
454 size_t tag_size
= gnutls_cipher_get_tag_size(algo
);
455 gnutls_datum_t key
= {
456 .data
= signing_key
->blob
.data
,
457 .size
= MIN(signing_key
->blob
.length
, key_size
),
459 uint64_t high_bits
= 0;
460 uint8_t iv
[AES_BLOCK_SIZE
] = {0};
461 giovec_t auth_iov
[count
+1];
462 size_t auth_iovcnt
= 0;
466 high_bits
= flags
& SMB2_HDR_FLAG_REDIRECT
;
467 if (opcode
== SMB2_OP_CANCEL
) {
468 high_bits
|= SMB2_HDR_FLAG_ASYNC
;
470 SBVAL(iv
, 0, msg_id
);
471 SBVAL(iv
, 8, high_bits
);
473 if (signing_key
->cipher_hnd
== NULL
) {
474 rc
= gnutls_aead_cipher_init(&signing_key
->cipher_hnd
,
478 return gnutls_error_to_ntstatus(rc
,
479 NT_STATUS_HMAC_NOT_SUPPORTED
);
483 SMB_ASSERT(key_size
== 16);
484 SMB_ASSERT(iv_size
== 12);
485 SMB_ASSERT(tag_size
== 16);
487 auth_iov
[auth_iovcnt
++] = (giovec_t
) {
488 .iov_base
= discard_const_p(uint8_t, hdr
),
489 .iov_len
= SMB2_HDR_SIGNATURE
,
491 auth_iov
[auth_iovcnt
++] = (giovec_t
) {
492 .iov_base
= discard_const_p(uint8_t, zero_sig
),
495 for (i
=1; i
< count
; i
++) {
496 auth_iov
[auth_iovcnt
++] = (giovec_t
) {
497 .iov_base
= discard_const_p(uint8_t, vector
[i
].iov_base
),
498 .iov_len
= vector
[i
].iov_len
,
502 status
= smb2_signing_gmac(signing_key
->cipher_hnd
,
509 if (!NT_STATUS_IS_OK(status
)) {
516 case SMB2_SIGNING_AES128_CMAC
:
517 #ifdef HAVE_GNUTLS_AES_CMAC
518 hmac_algo
= GNUTLS_MAC_AES_CMAC_128
;
520 #else /* NOT HAVE_GNUTLS_AES_CMAC */
522 struct aes_cmac_128_context ctx
;
523 uint8_t key
[AES_BLOCK_SIZE
] = {0};
526 signing_key
->blob
.data
,
527 MIN(signing_key
->blob
.length
, 16));
529 aes_cmac_128_init(&ctx
, key
);
530 aes_cmac_128_update(&ctx
, hdr
, SMB2_HDR_SIGNATURE
);
531 aes_cmac_128_update(&ctx
, zero_sig
, 16);
532 for (i
=1; i
< count
; i
++) {
533 aes_cmac_128_update(&ctx
,
534 (const uint8_t *)vector
[i
].iov_base
,
537 aes_cmac_128_final(&ctx
, signature
);
544 case SMB2_SIGNING_HMAC_SHA256
:
545 hmac_algo
= GNUTLS_MAC_SHA256
;
549 return NT_STATUS_HMAC_NOT_SUPPORTED
;
552 if (hmac_algo
!= GNUTLS_MAC_UNKNOWN
) {
553 uint8_t digest
[gnutls_hash_get_len(hmac_algo
)];
554 gnutls_datum_t key
= {
555 .data
= signing_key
->blob
.data
,
556 .size
= MIN(signing_key
->blob
.length
, 16),
560 if (signing_key
->hmac_hnd
== NULL
) {
561 rc
= gnutls_hmac_init(&signing_key
->hmac_hnd
,
566 return gnutls_error_to_ntstatus(rc
,
567 NT_STATUS_HMAC_NOT_SUPPORTED
);
571 rc
= gnutls_hmac(signing_key
->hmac_hnd
, hdr
, SMB2_HDR_SIGNATURE
);
573 return gnutls_error_to_ntstatus(rc
,
574 NT_STATUS_HMAC_NOT_SUPPORTED
);
576 rc
= gnutls_hmac(signing_key
->hmac_hnd
, zero_sig
, 16);
578 return gnutls_error_to_ntstatus(rc
,
579 NT_STATUS_HMAC_NOT_SUPPORTED
);
582 for (i
= 1; i
< count
; i
++) {
583 rc
= gnutls_hmac(signing_key
->hmac_hnd
,
587 return gnutls_error_to_ntstatus(rc
,
588 NT_STATUS_HMAC_NOT_SUPPORTED
);
591 gnutls_hmac_output(signing_key
->hmac_hnd
, digest
);
592 memcpy(signature
, digest
, 16);
597 return NT_STATUS_HMAC_NOT_SUPPORTED
;
600 NTSTATUS
smb2_signing_sign_pdu(struct smb2_signing_key
*signing_key
,
601 struct iovec
*vector
,
604 uint16_t sign_algo_id
;
614 * - (optional) SMB2 BODY DYN
615 * - (optional) PADDING
617 SMB_ASSERT(count
>= 2);
618 SMB_ASSERT(vector
[0].iov_len
== SMB2_HDR_BODY
);
619 SMB_ASSERT(count
<= 4);
621 hdr
= (uint8_t *)vector
[0].iov_base
;
623 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
624 if (session_id
== 0) {
626 * do not sign messages with a zero session_id.
627 * See MS-SMB2 3.2.4.1.1
632 if (!smb2_signing_key_valid(signing_key
)) {
633 DBG_WARNING("No signing key for SMB2 signing\n");
634 return NT_STATUS_ACCESS_DENIED
;
637 memset(hdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
639 SIVAL(hdr
, SMB2_HDR_FLAGS
, IVAL(hdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_SIGNED
);
641 sign_algo_id
= signing_key
->sign_algo_id
;
643 status
= smb2_signing_calc_signature(signing_key
,
648 if (!NT_STATUS_IS_OK(status
)) {
649 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
650 (unsigned)sign_algo_id
, nt_errstr(status
));
651 if (NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_ERROR
)) {
652 smb_panic(__location__
);
657 DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
658 (unsigned)sign_algo_id
));
660 memcpy(hdr
+ SMB2_HDR_SIGNATURE
, res
, 16);
665 NTSTATUS
smb2_signing_check_pdu(struct smb2_signing_key
*signing_key
,
666 const struct iovec
*vector
,
669 uint16_t sign_algo_id
;
680 * - (optional) SMB2 BODY DYN
681 * - (optional) PADDING
683 SMB_ASSERT(count
>= 2);
684 SMB_ASSERT(vector
[0].iov_len
== SMB2_HDR_BODY
);
685 SMB_ASSERT(count
<= 4);
687 hdr
= (const uint8_t *)vector
[0].iov_base
;
689 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
690 if (session_id
== 0) {
692 * do not sign messages with a zero session_id.
693 * See MS-SMB2 3.2.4.1.1
698 if (!smb2_signing_key_valid(signing_key
)) {
699 /* we don't have the session key yet */
703 sig
= hdr
+SMB2_HDR_SIGNATURE
;
705 sign_algo_id
= signing_key
->sign_algo_id
;
707 status
= smb2_signing_calc_signature(signing_key
,
712 if (!NT_STATUS_IS_OK(status
)) {
713 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
714 (unsigned)sign_algo_id
, nt_errstr(status
));
715 if (NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_ERROR
)) {
716 status
= NT_STATUS_ACCESS_DENIED
;
721 if (!mem_equal_const_time(res
, sig
, 16)) {
722 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
723 (unsigned)sign_algo_id
));
724 dump_data(0, sig
, 16);
725 dump_data(0, res
, 16);
726 return NT_STATUS_ACCESS_DENIED
;
732 NTSTATUS
smb2_key_derivation(const uint8_t *KI
, size_t KI_len
,
733 const uint8_t *Label
, size_t Label_len
,
734 const uint8_t *Context
, size_t Context_len
,
735 uint8_t *KO
, size_t KO_len
)
737 gnutls_hmac_hd_t hmac_hnd
= NULL
;
739 static const uint8_t zero
= 0;
740 const size_t digest_len
= gnutls_hash_get_len(GNUTLS_DIG_SHA256
);
741 uint8_t digest
[digest_len
];
743 uint32_t L
= KO_len
* 8;
746 if (KO_len
> digest_len
) {
747 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len
, digest_len
);
748 return NT_STATUS_INTERNAL_ERROR
;
756 DBG_ERR("KO_len[%zu] not supported\n", KO_len
);
757 return NT_STATUS_INTERNAL_ERROR
;
761 * a simplified version of
762 * "NIST Special Publication 800-108" section 5.1
765 rc
= gnutls_hmac_init(&hmac_hnd
,
770 return gnutls_error_to_ntstatus(rc
,
771 NT_STATUS_HMAC_NOT_SUPPORTED
);
775 rc
= gnutls_hmac(hmac_hnd
, buf
, sizeof(buf
));
777 return gnutls_error_to_ntstatus(rc
,
778 NT_STATUS_HMAC_NOT_SUPPORTED
);
780 rc
= gnutls_hmac(hmac_hnd
, Label
, Label_len
);
782 gnutls_hmac_deinit(hmac_hnd
, NULL
);
783 return gnutls_error_to_ntstatus(rc
,
784 NT_STATUS_HMAC_NOT_SUPPORTED
);
786 rc
= gnutls_hmac(hmac_hnd
, &zero
, 1);
788 gnutls_hmac_deinit(hmac_hnd
, NULL
);
789 return gnutls_error_to_ntstatus(rc
,
790 NT_STATUS_HMAC_NOT_SUPPORTED
);
792 rc
= gnutls_hmac(hmac_hnd
, Context
, Context_len
);
794 gnutls_hmac_deinit(hmac_hnd
, NULL
);
795 return gnutls_error_to_ntstatus(rc
,
796 NT_STATUS_HMAC_NOT_SUPPORTED
);
799 rc
= gnutls_hmac(hmac_hnd
, buf
, sizeof(buf
));
801 gnutls_hmac_deinit(hmac_hnd
, NULL
);
802 return gnutls_error_to_ntstatus(rc
,
803 NT_STATUS_HMAC_NOT_SUPPORTED
);
806 gnutls_hmac_deinit(hmac_hnd
, digest
);
808 memcpy(KO
, digest
, KO_len
);
815 NTSTATUS
smb2_signing_encrypt_pdu(struct smb2_signing_key
*encryption_key
,
816 struct iovec
*vector
,
819 #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
820 bool use_encryptv2
= false;
826 uint32_t iv_size
= 0;
827 uint32_t key_size
= 0;
829 gnutls_cipher_algorithm_t algo
= 0;
836 return NT_STATUS_INVALID_PARAMETER
;
839 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
840 return NT_STATUS_INVALID_PARAMETER
;
843 tf
= (uint8_t *)vector
[0].iov_base
;
845 if (!smb2_signing_key_valid(encryption_key
)) {
846 DBG_WARNING("No encryption key for SMB2 signing\n");
847 return NT_STATUS_ACCESS_DENIED
;
849 cipher_id
= encryption_key
->cipher_algo_id
;
851 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
853 m_total
= iov_buflen(&vector
[1], count
-1);
855 return NT_STATUS_BUFFER_TOO_SMALL
;
858 SSVAL(tf
, SMB2_TF_FLAGS
, SMB2_TF_FLAGS_ENCRYPTED
);
859 SIVAL(tf
, SMB2_TF_MSG_SIZE
, m_total
);
862 case SMB2_ENCRYPTION_AES128_CCM
:
863 algo
= GNUTLS_CIPHER_AES_128_CCM
;
864 iv_size
= SMB2_AES_128_CCM_NONCE_SIZE
;
865 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
866 use_encryptv2
= true;
869 case SMB2_ENCRYPTION_AES128_GCM
:
870 algo
= GNUTLS_CIPHER_AES_128_GCM
;
871 iv_size
= gnutls_cipher_get_iv_size(algo
);
872 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
873 use_encryptv2
= true;
876 case SMB2_ENCRYPTION_AES256_CCM
:
877 algo
= GNUTLS_CIPHER_AES_256_CCM
;
878 iv_size
= SMB2_AES_128_CCM_NONCE_SIZE
;
879 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
880 use_encryptv2
= true;
883 case SMB2_ENCRYPTION_AES256_GCM
:
884 algo
= GNUTLS_CIPHER_AES_256_GCM
;
885 iv_size
= gnutls_cipher_get_iv_size(algo
);
886 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
887 use_encryptv2
= true;
891 return NT_STATUS_INVALID_PARAMETER
;
894 key_size
= gnutls_cipher_get_key_size(algo
);
895 tag_size
= gnutls_cipher_get_tag_size(algo
);
897 if (key_size
!= encryption_key
->blob
.length
) {
898 return NT_STATUS_INTERNAL_ERROR
;
901 if (tag_size
!= 16) {
902 return NT_STATUS_INTERNAL_ERROR
;
905 key
= (gnutls_datum_t
) {
906 .data
= encryption_key
->blob
.data
,
910 iv
= (gnutls_datum_t
) {
911 .data
= tf
+ SMB2_TF_NONCE
,
915 if (encryption_key
->cipher_hnd
== NULL
) {
916 rc
= gnutls_aead_cipher_init(&encryption_key
->cipher_hnd
,
920 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
925 memset(tf
+ SMB2_TF_NONCE
+ iv_size
,
929 #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
931 uint8_t tag
[tag_size
];
932 giovec_t auth_iov
[1];
934 auth_iov
[0] = (giovec_t
) {
935 .iov_base
= tf
+ SMB2_TF_NONCE
,
939 rc
= gnutls_aead_cipher_encryptv2(encryption_key
->cipher_hnd
,
949 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
953 memcpy(tf
+ SMB2_TF_SIGNATURE
, tag
, tag_size
);
955 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
957 size_t ptext_size
= m_total
;
958 uint8_t *ptext
= NULL
;
959 size_t ctext_size
= m_total
+ tag_size
;
960 uint8_t *ctext
= NULL
;
963 TALLOC_CTX
*tmp_ctx
= NULL
;
966 * If we come from python bindings, we don't have a stackframe
967 * around, so use the NULL context.
969 * This is fine as we make sure we free the memory.
971 if (talloc_stackframe_exists()) {
972 tmp_ctx
= talloc_tos();
975 ptext
= talloc_size(tmp_ctx
, ptext_size
);
977 status
= NT_STATUS_NO_MEMORY
;
981 ctext
= talloc_size(tmp_ctx
, ctext_size
);
984 status
= NT_STATUS_NO_MEMORY
;
988 for (i
= 1; i
< count
; i
++) {
989 if (vector
[i
].iov_base
!= NULL
) {
995 len
+= vector
[i
].iov_len
;
996 if (len
> ptext_size
) {
999 status
= NT_STATUS_INTERNAL_ERROR
;
1004 rc
= gnutls_aead_cipher_encrypt(encryption_key
->cipher_hnd
,
1014 if (rc
< 0 || ctext_size
!= m_total
+ tag_size
) {
1017 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1022 for (i
= 1; i
< count
; i
++) {
1023 if (vector
[i
].iov_base
!= NULL
) {
1024 memcpy(vector
[i
].iov_base
,
1029 len
+= vector
[i
].iov_len
;
1032 memcpy(tf
+ SMB2_TF_SIGNATURE
, ctext
+ m_total
, tag_size
);
1038 DBG_INFO("Encrypted SMB2 message\n");
1040 status
= NT_STATUS_OK
;
1045 NTSTATUS
smb2_signing_decrypt_pdu(struct smb2_signing_key
*decryption_key
,
1046 struct iovec
*vector
,
1049 #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
1050 bool use_encryptv2
= false;
1057 uint32_t msg_size
= 0;
1058 uint32_t iv_size
= 0;
1059 uint32_t key_size
= 0;
1060 size_t tag_size
= 0;
1061 gnutls_cipher_algorithm_t algo
= 0;
1068 return NT_STATUS_INVALID_PARAMETER
;
1071 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
1072 return NT_STATUS_INVALID_PARAMETER
;
1075 tf
= (uint8_t *)vector
[0].iov_base
;
1077 if (!smb2_signing_key_valid(decryption_key
)) {
1078 DBG_WARNING("No decryption key for SMB2 signing\n");
1079 return NT_STATUS_ACCESS_DENIED
;
1081 cipher_id
= decryption_key
->cipher_algo_id
;
1083 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
1085 m_total
= iov_buflen(&vector
[1], count
-1);
1086 if (m_total
== -1) {
1087 return NT_STATUS_BUFFER_TOO_SMALL
;
1090 flags
= SVAL(tf
, SMB2_TF_FLAGS
);
1091 msg_size
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
1093 if (flags
!= SMB2_TF_FLAGS_ENCRYPTED
) {
1094 return NT_STATUS_ACCESS_DENIED
;
1097 if (msg_size
!= m_total
) {
1098 return NT_STATUS_INTERNAL_ERROR
;
1101 switch (cipher_id
) {
1102 case SMB2_ENCRYPTION_AES128_CCM
:
1103 algo
= GNUTLS_CIPHER_AES_128_CCM
;
1104 iv_size
= SMB2_AES_128_CCM_NONCE_SIZE
;
1105 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
1106 use_encryptv2
= true;
1109 case SMB2_ENCRYPTION_AES128_GCM
:
1110 algo
= GNUTLS_CIPHER_AES_128_GCM
;
1111 iv_size
= gnutls_cipher_get_iv_size(algo
);
1112 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
1113 use_encryptv2
= true;
1116 case SMB2_ENCRYPTION_AES256_CCM
:
1117 algo
= GNUTLS_CIPHER_AES_256_CCM
;
1118 iv_size
= SMB2_AES_128_CCM_NONCE_SIZE
;
1119 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
1120 use_encryptv2
= true;
1123 case SMB2_ENCRYPTION_AES256_GCM
:
1124 algo
= GNUTLS_CIPHER_AES_256_GCM
;
1125 iv_size
= gnutls_cipher_get_iv_size(algo
);
1126 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
1127 use_encryptv2
= true;
1131 return NT_STATUS_INVALID_PARAMETER
;
1134 key_size
= gnutls_cipher_get_key_size(algo
);
1135 tag_size
= gnutls_cipher_get_tag_size(algo
);
1137 if (key_size
!= decryption_key
->blob
.length
) {
1138 return NT_STATUS_INTERNAL_ERROR
;
1141 if (tag_size
!= 16) {
1142 return NT_STATUS_INTERNAL_ERROR
;
1145 key
= (gnutls_datum_t
) {
1146 .data
= decryption_key
->blob
.data
,
1150 iv
= (gnutls_datum_t
) {
1151 .data
= tf
+ SMB2_TF_NONCE
,
1155 if (decryption_key
->cipher_hnd
== NULL
) {
1156 rc
= gnutls_aead_cipher_init(&decryption_key
->cipher_hnd
,
1160 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1165 /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
1166 #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
1167 if (use_encryptv2
) {
1168 giovec_t auth_iov
[1];
1170 auth_iov
[0] = (giovec_t
) {
1171 .iov_base
= tf
+ SMB2_TF_NONCE
,
1175 rc
= gnutls_aead_cipher_decryptv2(decryption_key
->cipher_hnd
,
1182 tf
+ SMB2_TF_SIGNATURE
,
1185 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1189 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
1191 size_t ctext_size
= m_total
+ tag_size
;
1192 uint8_t *ctext
= NULL
;
1193 size_t ptext_size
= m_total
;
1194 uint8_t *ptext
= NULL
;
1197 TALLOC_CTX
*tmp_ctx
= NULL
;
1200 * If we come from python bindings, we don't have a stackframe
1201 * around, so use the NULL context.
1203 * This is fine as we make sure we free the memory.
1205 if (talloc_stackframe_exists()) {
1206 tmp_ctx
= talloc_tos();
1209 /* GnuTLS doesn't have a iovec API for decryption yet */
1211 ptext
= talloc_size(tmp_ctx
, ptext_size
);
1212 if (ptext
== NULL
) {
1213 status
= NT_STATUS_NO_MEMORY
;
1217 ctext
= talloc_size(tmp_ctx
, ctext_size
);
1218 if (ctext
== NULL
) {
1220 status
= NT_STATUS_NO_MEMORY
;
1225 for (i
= 1; i
< count
; i
++) {
1230 len
+= vector
[i
].iov_len
;
1232 if (len
!= m_total
) {
1235 status
= NT_STATUS_INTERNAL_ERROR
;
1240 tf
+ SMB2_TF_SIGNATURE
,
1243 /* This function will verify the tag */
1244 rc
= gnutls_aead_cipher_decrypt(decryption_key
->cipher_hnd
,
1257 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1260 #ifdef HAVE_GNUTLS_AEAD_CIPHER_DECRYPT_PTEXT_LEN_BUG
1262 * Note that gnutls before 3.5.2 had a bug and returned
1263 * *ptext_len = ctext_len, instead of
1264 * *ptext_len = ctext_len - tag_size
1266 if (ptext_size
!= ctext_size
) {
1269 rc
= GNUTLS_E_SHORT_MEMORY_BUFFER
;
1270 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1273 ptext_size
-= tag_size
;
1274 #endif /* HAVE_GNUTLS_AEAD_CIPHER_DECRYPT_PTEXT_LEN_BUG */
1275 if (ptext_size
!= m_total
) {
1278 rc
= GNUTLS_E_SHORT_MEMORY_BUFFER
;
1279 status
= gnutls_error_to_ntstatus(rc
, NT_STATUS_INTERNAL_ERROR
);
1284 for (i
= 1; i
< count
; i
++) {
1285 memcpy(vector
[i
].iov_base
,
1289 len
+= vector
[i
].iov_len
;
1296 DBG_INFO("Decrypted SMB2 message\n");
1298 status
= NT_STATUS_OK
;