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,
624 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;
655 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
657 m_total = iov_buflen(&vector[1], count-1);
659 return NT_STATUS_BUFFER_TOO_SMALL;
662 SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
663 SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
666 case SMB2_ENCRYPTION_AES128_CCM:
667 algo = GNUTLS_CIPHER_AES_128_CCM;
668 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
670 case SMB2_ENCRYPTION_AES128_GCM:
671 algo = GNUTLS_CIPHER_AES_128_GCM;
672 iv_size = gnutls_cipher_get_iv_size(algo);
675 return NT_STATUS_INVALID_PARAMETER;
678 key_size = gnutls_cipher_get_key_size(algo);
679 tag_size = gnutls_cipher_get_tag_size(algo);
681 if (key_size > sizeof(_key)) {
682 return NT_STATUS_BUFFER_TOO_SMALL;
685 key = (gnutls_datum_t) {
691 encryption_key->blob.data,
692 MIN(encryption_key->blob.length, key.size));
694 iv = (gnutls_datum_t) {
695 .data = tf + SMB2_TF_NONCE,
699 if (encryption_key->cipher_hnd == NULL) {
700 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
704 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
709 memset(tf + SMB2_TF_NONCE + iv_size,
713 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
715 uint8_t tag[tag_size];
716 giovec_t auth_iov[1];
718 auth_iov[0] = (giovec_t) {
719 .iov_base = tf + SMB2_TF_NONCE,
723 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
733 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
737 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
739 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
741 size_t ptext_size = m_total;
742 uint8_t *ptext = NULL;
743 size_t ctext_size = m_total + tag_size;
744 uint8_t *ctext = NULL;
747 TALLOC_CTX *tmp_ctx = NULL;
750 * If we come from python bindings, we don't have a stackframe
751 * around, so use the NULL context.
753 * This is fine as we make sure we free the memory.
755 if (talloc_stackframe_exists()) {
756 tmp_ctx = talloc_tos();
759 ptext = talloc_size(tmp_ctx, ptext_size);
761 status = NT_STATUS_NO_MEMORY;
765 ctext = talloc_size(tmp_ctx, ctext_size);
768 status = NT_STATUS_NO_MEMORY;
772 for (i = 1; i < count; i++) {
777 len += vector[i].iov_len;
778 if (len > ptext_size) {
781 status = NT_STATUS_INTERNAL_ERROR;
786 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
796 if (rc < 0 || ctext_size != m_total + tag_size) {
799 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
804 for (i = 1; i < count; i++) {
805 memcpy(vector[i].iov_base,
809 len += vector[i].iov_len;
812 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
817 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
819 DBG_INFO("Encrypted SMB2 message\n");
821 status = NT_STATUS_OK;
828 NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
830 struct iovec *vector,
837 uint32_t msg_size = 0;
838 uint32_t iv_size = 0;
839 uint32_t key_size = 0;
841 uint8_t _key[16] = {0};
842 gnutls_cipher_algorithm_t algo = 0;
849 return NT_STATUS_INVALID_PARAMETER;
852 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
853 return NT_STATUS_INVALID_PARAMETER;
856 tf = (uint8_t *)vector[0].iov_base;
858 if (!smb2_signing_key_valid(decryption_key)) {
859 DBG_WARNING("No decryption key for SMB2 signing\n");
860 return NT_STATUS_ACCESS_DENIED;
863 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
865 m_total = iov_buflen(&vector[1], count-1);
867 return NT_STATUS_BUFFER_TOO_SMALL;
870 flags = SVAL(tf, SMB2_TF_FLAGS);
871 msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
873 if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
874 return NT_STATUS_ACCESS_DENIED;
877 if (msg_size != m_total) {
878 return NT_STATUS_INTERNAL_ERROR;
882 case SMB2_ENCRYPTION_AES128_CCM:
883 algo = GNUTLS_CIPHER_AES_128_CCM;
884 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
886 case SMB2_ENCRYPTION_AES128_GCM:
887 algo = GNUTLS_CIPHER_AES_128_GCM;
888 iv_size = gnutls_cipher_get_iv_size(algo);
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 > sizeof(_key)) {
898 return NT_STATUS_BUFFER_TOO_SMALL;
901 key = (gnutls_datum_t) {
907 decryption_key->blob.data,
908 MIN(decryption_key->blob.length, key.size));
910 iv = (gnutls_datum_t) {
911 .data = tf + SMB2_TF_NONCE,
915 if (decryption_key->cipher_hnd == NULL) {
916 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
920 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
925 /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
926 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
928 giovec_t auth_iov[1];
930 auth_iov[0] = (giovec_t) {
931 .iov_base = tf + SMB2_TF_NONCE,
935 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
942 tf + SMB2_TF_SIGNATURE,
945 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
949 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
951 size_t ctext_size = m_total + tag_size;
952 uint8_t *ctext = NULL;
953 size_t ptext_size = m_total;
954 uint8_t *ptext = NULL;
957 TALLOC_CTX *tmp_ctx = NULL;
960 * If we come from python bindings, we don't have a stackframe
961 * around, so use the NULL context.
963 * This is fine as we make sure we free the memory.
965 if (talloc_stackframe_exists()) {
966 tmp_ctx = talloc_tos();
969 /* GnuTLS doesn't have a iovec API for decryption yet */
971 ptext = talloc_size(tmp_ctx, ptext_size);
973 status = NT_STATUS_NO_MEMORY;
977 ctext = talloc_size(tmp_ctx, ctext_size);
980 status = NT_STATUS_NO_MEMORY;
985 for (i = 1; i < count; i++) {
990 len += vector[i].iov_len;
992 if (len != m_total) {
995 status = NT_STATUS_INTERNAL_ERROR;
1000 tf + SMB2_TF_SIGNATURE,
1003 /* This function will verify the tag */
1004 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
1014 if (rc < 0 || ptext_size != m_total) {
1017 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1022 for (i = 1; i < count; i++) {
1023 memcpy(vector[i].iov_base,
1027 len += vector[i].iov_len;
1033 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
1035 DBG_INFO("Decrypted SMB2 message\n");
1037 status = NT_STATUS_OK;