LCOV - code coverage report
Current view: top level - libcli/smb - smb2_signing.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 416 596 69.8 %
Date: 2024-04-21 15:09:00 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB2 signing
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             : 
       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.
      11             : 
      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.
      16             : 
      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/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      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"
      29             : 
      30             : #include "lib/crypto/gnutls_helpers.h"
      31             : 
      32       48463 : void smb2_signing_derivations_fill_const_stack(struct smb2_signing_derivations *ds,
      33             :                                                enum protocol_types protocol,
      34             :                                                const DATA_BLOB preauth_hash)
      35             : {
      36       48463 :         *ds = (struct smb2_signing_derivations) { .signing = NULL, };
      37             : 
      38       48463 :         if (protocol >= PROTOCOL_SMB3_11) {
      39       41898 :                 struct smb2_signing_derivation *d = NULL;
      40             : 
      41       41898 :                 SMB_ASSERT(preauth_hash.length != 0);
      42             : 
      43       41898 :                 d = &ds->__signing;
      44       41898 :                 ds->signing = d;
      45       41898 :                 d->label = data_blob_string_const_null("SMBSigningKey");
      46       41898 :                 d->context = preauth_hash;
      47             : 
      48       41898 :                 d = &ds->__cipher_c2s;
      49       41898 :                 ds->cipher_c2s = d;
      50       41898 :                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
      51       41898 :                 d->context = preauth_hash;
      52             : 
      53       41898 :                 d = &ds->__cipher_s2c;
      54       41898 :                 ds->cipher_s2c = d;
      55       41898 :                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
      56       41898 :                 d->context = preauth_hash;
      57             : 
      58       41898 :                 d = &ds->__application;
      59       41898 :                 ds->application = d;
      60       41898 :                 d->label = data_blob_string_const_null("SMBAppKey");
      61       41898 :                 d->context = preauth_hash;
      62             : 
      63        6565 :         } else if (protocol >= PROTOCOL_SMB3_00) {
      64         160 :                 struct smb2_signing_derivation *d = NULL;
      65             : 
      66         160 :                 d = &ds->__signing;
      67         160 :                 ds->signing = d;
      68         160 :                 d->label = data_blob_string_const_null("SMB2AESCMAC");
      69         160 :                 d->context = data_blob_string_const_null("SmbSign");
      70             : 
      71         160 :                 d = &ds->__cipher_c2s;
      72         160 :                 ds->cipher_c2s = d;
      73         160 :                 d->label = data_blob_string_const_null("SMB2AESCCM");
      74         160 :                 d->context = data_blob_string_const_null("ServerIn ");
      75             : 
      76         160 :                 d = &ds->__cipher_s2c;
      77         160 :                 ds->cipher_s2c = d;
      78         160 :                 d->label = data_blob_string_const_null("SMB2AESCCM");
      79         160 :                 d->context = data_blob_string_const_null("ServerOut");
      80             : 
      81         160 :                 d = &ds->__application;
      82         160 :                 ds->application = d;
      83         160 :                 d->label = data_blob_string_const_null("SMB2APP");
      84         160 :                 d->context = data_blob_string_const_null("SmbRpc");
      85             :         }
      86       48463 : }
      87             : 
      88      321784 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
      89             : {
      90      321784 :         if (key->hmac_hnd != NULL) {
      91        7790 :                 gnutls_hmac_deinit(key->hmac_hnd, NULL);
      92        7790 :                 key->hmac_hnd = NULL;
      93             :         }
      94             : 
      95      321784 :         if (key->cipher_hnd != NULL) {
      96       48726 :                 gnutls_aead_cipher_deinit(key->cipher_hnd);
      97       48726 :                 key->cipher_hnd = NULL;
      98             :         }
      99             : 
     100      321784 :         return 0;
     101             : }
     102             : 
     103       54952 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
     104             :                                const struct smb2_signing_key *src,
     105             :                                struct smb2_signing_key **_dst)
     106             : {
     107       54952 :         struct smb2_signing_key *dst = NULL;
     108             : 
     109       54952 :         dst = talloc_zero(mem_ctx, struct smb2_signing_key);
     110       54952 :         if (dst == NULL) {
     111           0 :                 return NT_STATUS_NO_MEMORY;
     112             :         }
     113       54952 :         talloc_set_destructor(dst, smb2_signing_key_destructor);
     114             : 
     115       54952 :         dst->sign_algo_id = src->sign_algo_id;
     116       54952 :         dst->cipher_algo_id = src->cipher_algo_id;
     117             : 
     118       54952 :         if (src->blob.length == 0) {
     119           0 :                 *_dst = dst;
     120           0 :                 return NT_STATUS_OK;
     121             :         }
     122             : 
     123       54952 :         dst->blob = data_blob_talloc_zero(dst, src->blob.length);
     124       54952 :         if (dst->blob.length == 0) {
     125           0 :                 TALLOC_FREE(dst);
     126           0 :                 return NT_STATUS_NO_MEMORY;
     127             :         }
     128       54952 :         talloc_keep_secret(dst->blob.data);
     129       54952 :         memcpy(dst->blob.data, src->blob.data, dst->blob.length);
     130             : 
     131       54952 :         *_dst = dst;
     132       54952 :         return NT_STATUS_OK;
     133             : }
     134             : 
     135      296500 : static NTSTATUS smb2_signing_key_create(TALLOC_CTX *mem_ctx,
     136             :                                         uint16_t sign_algo_id,
     137             :                                         uint16_t cipher_algo_id,
     138             :                                         const DATA_BLOB *master_key,
     139             :                                         const struct smb2_signing_derivation *d,
     140             :                                         struct smb2_signing_key **_key)
     141             : {
     142      296500 :         struct smb2_signing_key *key = NULL;
     143      296500 :         size_t in_key_length = 16;
     144      296500 :         size_t out_key_length = 16;
     145        7597 :         NTSTATUS status;
     146             : 
     147      296500 :         if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
     148      207181 :                 SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
     149             :         }
     150      296500 :         if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
     151       89319 :                 SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
     152             :         }
     153             : 
     154      296500 :         key = talloc_zero(mem_ctx, struct smb2_signing_key);
     155      296500 :         if (key == NULL) {
     156           0 :                 return NT_STATUS_NO_MEMORY;
     157             :         }
     158      296500 :         talloc_set_destructor(key, smb2_signing_key_destructor);
     159             : 
     160      296500 :         key->sign_algo_id = sign_algo_id;
     161      296500 :         key->cipher_algo_id = cipher_algo_id;
     162             : 
     163      296500 :         if (master_key == NULL) {
     164      106622 :                 SMB_ASSERT(d == NULL);
     165             : 
     166      106622 :                 *_key = key;
     167      106622 :                 return NT_STATUS_OK;
     168             :         }
     169             : 
     170             :         /*
     171             :          * Per default use the full key.
     172             :          */
     173      189878 :         in_key_length = out_key_length = master_key->length;
     174      189878 :         switch (sign_algo_id) {
     175       85698 :         case SMB2_SIGNING_INVALID_ALGO:
     176             :                 /*
     177             :                  * This means we're processing cipher_algo_id below
     178             :                  */
     179       85698 :                 break;
     180        5694 :         case SMB2_SIGNING_MD5_SMB1:
     181        5694 :                 SMB_ASSERT(d == NULL);
     182        5561 :                 break;
     183       96022 :         case SMB2_SIGNING_HMAC_SHA256:
     184             :         case SMB2_SIGNING_AES128_CMAC:
     185             :         case SMB2_SIGNING_AES128_GMAC:
     186             :                 /*
     187             :                  * signing keys are padded or truncated to
     188             :                  * 16 bytes.
     189             :                  *
     190             :                  * Even with master_key->length = 0,
     191             :                  * we need to use 16 zeros.
     192             :                  */
     193       96022 :                 in_key_length = out_key_length = 16;
     194       96022 :                 break;
     195           0 :         default:
     196           0 :                 DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id);
     197           0 :                 return NT_STATUS_HMAC_NOT_SUPPORTED;
     198             :         }
     199      189878 :         switch (cipher_algo_id) {
     200       99069 :         case SMB2_ENCRYPTION_INVALID_ALGO:
     201             :                 /*
     202             :                  * This means we're processing sign_algo_id above
     203             :                  */
     204       99069 :                 break;
     205        8234 :         case SMB2_ENCRYPTION_NONE:
     206             :                 /*
     207             :                  * No encryption negotiated.
     208             :                  */
     209        8234 :                 break;
     210       79804 :         case SMB2_ENCRYPTION_AES128_CCM:
     211             :         case SMB2_ENCRYPTION_AES128_GCM:
     212             :                 /*
     213             :                  * encryption keys are padded or truncated to
     214             :                  * 16 bytes.
     215             :                  */
     216       79804 :                 if (master_key->length == 0) {
     217           0 :                         DBG_ERR("cipher_algo_id[%u] without key\n",
     218             :                                 cipher_algo_id);
     219           0 :                         return NT_STATUS_NO_USER_SESSION_KEY;
     220             :                 }
     221       77384 :                 in_key_length = out_key_length = 16;
     222       77384 :                 break;
     223          96 :         case SMB2_ENCRYPTION_AES256_CCM:
     224             :         case SMB2_ENCRYPTION_AES256_GCM:
     225             :                 /*
     226             :                  * AES256 uses the available input and
     227             :                  * generated a 32 byte encryption key.
     228             :                  */
     229          96 :                 if (master_key->length == 0) {
     230           0 :                         DBG_ERR("cipher_algo_id[%u] without key\n",
     231             :                                 cipher_algo_id);
     232           0 :                         return NT_STATUS_NO_USER_SESSION_KEY;
     233             :                 }
     234          80 :                 out_key_length = 32;
     235          80 :                 break;
     236           0 :         default:
     237           0 :                 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id);
     238           0 :                 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG;
     239             :         }
     240             : 
     241      187442 :         if (out_key_length == 0) {
     242           0 :                 *_key = key;
     243           0 :                 return NT_STATUS_OK;
     244             :         }
     245             : 
     246      189878 :         key->blob = data_blob_talloc_zero(key, out_key_length);
     247      189878 :         if (key->blob.length == 0) {
     248           0 :                 TALLOC_FREE(key);
     249           0 :                 return NT_STATUS_NO_MEMORY;
     250             :         }
     251      189878 :         talloc_keep_secret(key->blob.data);
     252      189878 :         memcpy(key->blob.data,
     253      189878 :                master_key->data,
     254      189878 :                MIN(key->blob.length, master_key->length));
     255             : 
     256      189878 :         if (d == NULL) {
     257       26380 :                 *_key = key;
     258       26380 :                 return NT_STATUS_OK;
     259             :         }
     260             : 
     261      163498 :         status = samba_gnutls_sp800_108_derive_key(key->blob.data,
     262             :                                                    in_key_length,
     263             :                                                    NULL,
     264             :                                                    0,
     265      163498 :                                                    d->label.data,
     266      163498 :                                                    d->label.length,
     267      163498 :                                                    d->context.data,
     268      163498 :                                                    d->context.length,
     269             :                                                    GNUTLS_MAC_SHA256,
     270             :                                                    key->blob.data,
     271             :                                                    out_key_length);
     272      163498 :         if (!NT_STATUS_IS_OK(status)) {
     273           0 :                 TALLOC_FREE(key);
     274           0 :                 return status;
     275             :         }
     276             : 
     277      163498 :         *_key = key;
     278      163498 :         return NT_STATUS_OK;
     279             : }
     280             : 
     281      207181 : NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
     282             :                                       uint16_t sign_algo_id,
     283             :                                       const DATA_BLOB *master_key,
     284             :                                       const struct smb2_signing_derivation *d,
     285             :                                       struct smb2_signing_key **_key)
     286             : {
     287      207181 :         return smb2_signing_key_create(mem_ctx,
     288             :                                        sign_algo_id,
     289             :                                        SMB2_ENCRYPTION_INVALID_ALGO,
     290             :                                        master_key,
     291             :                                        d,
     292             :                                        _key);
     293             : }
     294             : 
     295       89319 : NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
     296             :                                         uint16_t cipher_algo_id,
     297             :                                         const DATA_BLOB *master_key,
     298             :                                         const struct smb2_signing_derivation *d,
     299             :                                         struct smb2_signing_key **_key)
     300             : {
     301       89319 :         return smb2_signing_key_create(mem_ctx,
     302             :                                        SMB2_SIGNING_INVALID_ALGO,
     303             :                                        cipher_algo_id,
     304             :                                        master_key,
     305             :                                        d,
     306             :                                        _key);
     307             : }
     308             : 
     309    10448149 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
     310             : {
     311    10448149 :         if (key == NULL) {
     312      792630 :                 return false;
     313             :         }
     314             : 
     315     9652041 :         if (key->blob.length == 0 || key->blob.data == NULL) {
     316      283320 :                 return false;
     317             :         }
     318             : 
     319     9266806 :         return true;
     320             : }
     321             : 
     322     2563429 : static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd,
     323             :                                   const uint8_t *iv, size_t iv_size,
     324             :                                   const giovec_t *auth_iov, uint8_t auth_iovcnt,
     325             :                                   uint8_t *tag, size_t _tag_size)
     326             : {
     327     2563429 :         size_t tag_size = _tag_size;
     328       37218 :         int rc;
     329             : 
     330     2563429 :         rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
     331             :                                           iv, iv_size,
     332             :                                           auth_iov, auth_iovcnt,
     333             :                                           NULL, 0,
     334             :                                           tag, &tag_size);
     335     2563429 :         if (rc < 0) {
     336           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     337             :         }
     338             : 
     339     2563429 :         return NT_STATUS_OK;
     340             : }
     341             : 
     342     3688969 : static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
     343             :                                             uint16_t sign_algo_id,
     344             :                                             const struct iovec *vector,
     345             :                                             int count,
     346             :                                             uint8_t signature[16])
     347             : {
     348     3688969 :         const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
     349       38676 :         uint16_t opcode;
     350       38676 :         uint32_t flags;
     351       38676 :         uint64_t msg_id;
     352       38676 :         static const uint8_t zero_sig[16] = { 0, };
     353     3688969 :         gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
     354       38676 :         int i;
     355             : 
     356             :         /*
     357             :          * We expect
     358             :          * - SMB2 HDR
     359             :          * - SMB2 BODY FIXED
     360             :          * - (optional) SMB2 BODY DYN
     361             :          * - (optional) PADDING
     362             :          */
     363     3688969 :         SMB_ASSERT(count >= 2);
     364     3688969 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     365     3688969 :         SMB_ASSERT(count <= 4);
     366             : 
     367     3688969 :         opcode = SVAL(hdr, SMB2_HDR_OPCODE);
     368     3688969 :         flags = IVAL(hdr, SMB2_HDR_FLAGS);
     369     3688969 :         if (flags & SMB2_HDR_FLAG_REDIRECT) {
     370     1863892 :                 NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
     371     1863892 :                 if (NT_STATUS_EQUAL(pdu_status, NT_STATUS_PENDING)) {
     372           0 :                         DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode);
     373           0 :                         return NT_STATUS_INTERNAL_ERROR;
     374             :                 }
     375     1863892 :                 if (opcode == SMB2_OP_CANCEL) {
     376           0 :                         DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
     377           0 :                         return NT_STATUS_INTERNAL_ERROR;
     378             :                 }
     379             :         }
     380     3688969 :         msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
     381     3688969 :         if (msg_id == 0) {
     382          42 :                 if (opcode != SMB2_OP_CANCEL ||
     383           8 :                     sign_algo_id >= SMB2_SIGNING_AES128_GMAC)
     384             :                 {
     385           0 :                         DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
     386           0 :                         return NT_STATUS_INTERNAL_ERROR;
     387             :                 }
     388             :                 /*
     389             :                  * Legacy algorithms allow MID 0
     390             :                  * for cancel requests
     391             :                  */
     392             :         }
     393     3688969 :         if (msg_id == UINT64_MAX) {
     394           0 :                 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
     395           0 :                 return NT_STATUS_INTERNAL_ERROR;
     396             :         }
     397             : 
     398     3688969 :         switch (sign_algo_id) {
     399     2563429 :         case SMB2_SIGNING_AES128_GMAC: {
     400     2563429 :                 gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
     401     2563429 :                 uint32_t key_size = gnutls_cipher_get_key_size(algo);
     402     2563429 :                 uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
     403     2563429 :                 size_t tag_size = gnutls_cipher_get_tag_size(algo);
     404     2563429 :                 gnutls_datum_t key = {
     405     2563429 :                         .data = signing_key->blob.data,
     406     2563429 :                         .size = MIN(signing_key->blob.length, key_size),
     407             :                 };
     408     2563429 :                 uint64_t high_bits = 0;
     409     2563429 :                 uint8_t iv[AES_BLOCK_SIZE] = {0};
     410     2563429 :                 giovec_t auth_iov[count+1];
     411     2563429 :                 size_t auth_iovcnt = 0;
     412       37218 :                 NTSTATUS status;
     413       37218 :                 int rc;
     414             : 
     415     2563429 :                 high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
     416     2563429 :                 if (opcode == SMB2_OP_CANCEL) {
     417          38 :                         high_bits |= SMB2_HDR_FLAG_ASYNC;
     418             :                 }
     419     2563429 :                 SBVAL(iv, 0, msg_id);
     420     2563429 :                 SBVAL(iv, 8, high_bits);
     421             : 
     422     2563429 :                 if (signing_key->cipher_hnd == NULL) {
     423       42660 :                         rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
     424             :                                                      algo,
     425             :                                                      &key);
     426       42660 :                         if (rc < 0) {
     427           0 :                                 return gnutls_error_to_ntstatus(rc,
     428             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     429             :                         }
     430             :                 }
     431             : 
     432     2563429 :                 SMB_ASSERT(key_size == 16);
     433     2563429 :                 SMB_ASSERT(iv_size == 12);
     434     2563429 :                 SMB_ASSERT(tag_size == 16);
     435             : 
     436     2563429 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     437             :                         .iov_base = discard_const_p(uint8_t, hdr),
     438             :                         .iov_len  = SMB2_HDR_SIGNATURE,
     439             :                 };
     440     2563429 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     441             :                         .iov_base = discard_const_p(uint8_t, zero_sig),
     442             :                         .iov_len  = 16,
     443             :                 };
     444     7669900 :                 for (i=1; i < count; i++) {
     445     5106471 :                         auth_iov[auth_iovcnt++] = (giovec_t) {
     446     5106471 :                                 .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
     447     5106471 :                                 .iov_len  = vector[i].iov_len,
     448             :                         };
     449             :                 }
     450             : 
     451     2563429 :                 status = smb2_signing_gmac(signing_key->cipher_hnd,
     452             :                                            iv,
     453             :                                            iv_size,
     454             :                                            auth_iov,
     455             :                                            auth_iovcnt,
     456             :                                            signature,
     457             :                                            tag_size);
     458     2563429 :                 if (!NT_STATUS_IS_OK(status)) {
     459           0 :                         return status;
     460             :                 }
     461             : 
     462     2563429 :                 return NT_STATUS_OK;
     463             :         }       break;
     464             : 
     465        2988 :         case SMB2_SIGNING_AES128_CMAC:
     466        2988 :                 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
     467        2988 :                 break;
     468     1121940 :         case SMB2_SIGNING_HMAC_SHA256:
     469     1121940 :                 hmac_algo = GNUTLS_MAC_SHA256;
     470     1121940 :                 break;
     471             : 
     472           0 :         default:
     473           0 :                 return NT_STATUS_HMAC_NOT_SUPPORTED;
     474             :         }
     475             : 
     476     1125540 :         if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
     477     1125540 :                 uint8_t digest[gnutls_hmac_get_len(hmac_algo)];
     478     1125540 :                 gnutls_datum_t key = {
     479     1125540 :                         .data = signing_key->blob.data,
     480     1125540 :                         .size = MIN(signing_key->blob.length, 16),
     481             :                 };
     482        1458 :                 int rc;
     483             : 
     484     1125540 :                 if (signing_key->hmac_hnd == NULL) {
     485        7832 :                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
     486             :                                               hmac_algo,
     487        7552 :                                               key.data,
     488        7552 :                                               key.size);
     489        7832 :                         if (rc < 0) {
     490           0 :                                 return gnutls_error_to_ntstatus(rc,
     491             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     492             :                         }
     493             :                 }
     494             : 
     495     1125540 :                 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
     496     1125540 :                 if (rc < 0) {
     497           0 :                         return gnutls_error_to_ntstatus(rc,
     498             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     499             :                 }
     500     1125540 :                 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
     501     1125540 :                 if (rc < 0) {
     502           0 :                         return gnutls_error_to_ntstatus(rc,
     503             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     504             :                 }
     505             : 
     506     3363906 :                 for (i = 1; i < count; i++) {
     507     2241278 :                         rc = gnutls_hmac(signing_key->hmac_hnd,
     508     2238366 :                                          vector[i].iov_base,
     509     2238366 :                                          vector[i].iov_len);
     510     2238366 :                         if (rc < 0) {
     511           0 :                                 return gnutls_error_to_ntstatus(rc,
     512             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     513             :                         }
     514             :                 }
     515     1125540 :                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
     516     1125540 :                 memcpy(signature, digest, 16);
     517     1125540 :                 ZERO_ARRAY(digest);
     518     1125540 :                 return NT_STATUS_OK;
     519             :         }
     520             : 
     521           0 :         return NT_STATUS_HMAC_NOT_SUPPORTED;
     522             : }
     523             : 
     524     1847617 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
     525             :                                struct iovec *vector,
     526             :                                int count)
     527             : {
     528       19674 :         uint16_t sign_algo_id;
     529       19674 :         uint8_t *hdr;
     530       19674 :         uint64_t session_id;
     531       19674 :         uint8_t res[16];
     532       19674 :         NTSTATUS status;
     533             : 
     534             :         /*
     535             :          * We expect
     536             :          * - SMB2 HDR
     537             :          * - SMB2 BODY FIXED
     538             :          * - (optional) SMB2 BODY DYN
     539             :          * - (optional) PADDING
     540             :          */
     541     1847617 :         SMB_ASSERT(count >= 2);
     542     1847617 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     543     1847617 :         SMB_ASSERT(count <= 4);
     544             : 
     545     1847617 :         hdr = (uint8_t *)vector[0].iov_base;
     546             : 
     547     1847617 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     548     1847617 :         if (session_id == 0) {
     549             :                 /*
     550             :                  * do not sign messages with a zero session_id.
     551             :                  * See MS-SMB2 3.2.4.1.1
     552             :                  */
     553           0 :                 return NT_STATUS_OK;
     554             :         }
     555             : 
     556     1847617 :         if (!smb2_signing_key_valid(signing_key)) {
     557           0 :                 DBG_WARNING("No signing key for SMB2 signing\n");
     558           0 :                 return NT_STATUS_ACCESS_DENIED;
     559             :         }
     560             : 
     561     1847617 :         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
     562             : 
     563     1847617 :         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
     564             : 
     565     1847617 :         sign_algo_id = signing_key->sign_algo_id;
     566             : 
     567     1847617 :         status = smb2_signing_calc_signature(signing_key,
     568             :                                              sign_algo_id,
     569             :                                              vector,
     570             :                                              count,
     571             :                                              res);
     572     1847617 :         if (!NT_STATUS_IS_OK(status)) {
     573           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     574             :                         (unsigned)sign_algo_id, nt_errstr(status));
     575           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     576           0 :                         smb_panic(__location__);
     577             :                 }
     578           0 :                 return status;
     579             :         }
     580             : 
     581     1847617 :         DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
     582             :                  (unsigned)sign_algo_id));
     583             : 
     584     1847617 :         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
     585             : 
     586     1847617 :         return NT_STATUS_OK;
     587             : }
     588             : 
     589     1841352 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
     590             :                                 const struct iovec *vector,
     591             :                                 int count)
     592             : {
     593       19002 :         uint16_t sign_algo_id;
     594       19002 :         const uint8_t *hdr;
     595       19002 :         const uint8_t *sig;
     596       19002 :         uint64_t session_id;
     597       19002 :         uint8_t res[16];
     598       19002 :         NTSTATUS status;
     599             : 
     600             :         /*
     601             :          * We expect
     602             :          * - SMB2 HDR
     603             :          * - SMB2 BODY FIXED
     604             :          * - (optional) SMB2 BODY DYN
     605             :          * - (optional) PADDING
     606             :          */
     607     1841352 :         SMB_ASSERT(count >= 2);
     608     1841352 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     609     1841352 :         SMB_ASSERT(count <= 4);
     610             : 
     611     1841352 :         hdr = (const uint8_t *)vector[0].iov_base;
     612             : 
     613     1841352 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     614     1841352 :         if (session_id == 0) {
     615             :                 /*
     616             :                  * do not sign messages with a zero session_id.
     617             :                  * See MS-SMB2 3.2.4.1.1
     618             :                  */
     619           0 :                 return NT_STATUS_OK;
     620             :         }
     621             : 
     622     1841352 :         if (!smb2_signing_key_valid(signing_key)) {
     623             :                 /* we don't have the session key yet */
     624           0 :                 return NT_STATUS_OK;
     625             :         }
     626             : 
     627     1841352 :         sig = hdr+SMB2_HDR_SIGNATURE;
     628             : 
     629     1841352 :         sign_algo_id = signing_key->sign_algo_id;
     630             : 
     631     1841352 :         status = smb2_signing_calc_signature(signing_key,
     632             :                                              sign_algo_id,
     633             :                                              vector,
     634             :                                              count,
     635             :                                              res);
     636     1841352 :         if (!NT_STATUS_IS_OK(status)) {
     637           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     638             :                         (unsigned)sign_algo_id, nt_errstr(status));
     639           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     640           0 :                         status = NT_STATUS_ACCESS_DENIED;
     641             :                 }
     642           0 :                 return status;
     643             :         }
     644             : 
     645     1841352 :         if (!mem_equal_const_time(res, sig, 16)) {
     646         256 :                 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
     647             :                          (unsigned)sign_algo_id));
     648         256 :                 dump_data(0, sig, 16);
     649         256 :                 dump_data(0, res, 16);
     650         256 :                 return NT_STATUS_ACCESS_DENIED;
     651             :         }
     652             : 
     653     1841096 :         return NT_STATUS_OK;
     654             : }
     655             : 
     656       14767 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
     657             :                                   struct iovec *vector,
     658             :                                   int count)
     659             : {
     660       14767 :         bool use_encryptv2 = false;
     661         990 :         uint16_t cipher_id;
     662         990 :         uint8_t *tf;
     663         990 :         size_t a_total;
     664         990 :         ssize_t m_total;
     665       14767 :         uint32_t iv_size = 0;
     666       14767 :         uint32_t key_size = 0;
     667       14767 :         size_t tag_size = 0;
     668       14767 :         gnutls_cipher_algorithm_t algo = 0;
     669         990 :         gnutls_datum_t key;
     670         990 :         gnutls_datum_t iv;
     671         990 :         NTSTATUS status;
     672         990 :         int rc;
     673             : 
     674       14767 :         if (count < 1) {
     675           0 :                 return NT_STATUS_INVALID_PARAMETER;
     676             :         }
     677             : 
     678       14767 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
     679           0 :                 return NT_STATUS_INVALID_PARAMETER;
     680             :         }
     681             : 
     682       14767 :         tf = (uint8_t *)vector[0].iov_base;
     683             : 
     684       14767 :         if (!smb2_signing_key_valid(encryption_key)) {
     685           0 :                 DBG_WARNING("No encryption key for SMB2 signing\n");
     686           0 :                 return NT_STATUS_ACCESS_DENIED;
     687             :         }
     688       14767 :         cipher_id = encryption_key->cipher_algo_id;
     689             : 
     690       14767 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
     691             : 
     692       14767 :         m_total = iov_buflen(&vector[1], count-1);
     693       14767 :         if (m_total == -1) {
     694           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     695             :         }
     696             : 
     697       14767 :         SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
     698       14767 :         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
     699             : 
     700       14767 :         switch (cipher_id) {
     701        1116 :         case SMB2_ENCRYPTION_AES128_CCM:
     702        1116 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
     703        1116 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     704             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     705        1116 :                 use_encryptv2 = true;
     706             : #endif
     707        1116 :                 break;
     708       13007 :         case SMB2_ENCRYPTION_AES128_GCM:
     709       13007 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
     710       13007 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     711       13007 :                 use_encryptv2 = true;
     712       13007 :                 break;
     713         216 :         case SMB2_ENCRYPTION_AES256_CCM:
     714         216 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
     715         216 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     716             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     717         216 :                 use_encryptv2 = true;
     718             : #endif
     719         216 :                 break;
     720         216 :         case SMB2_ENCRYPTION_AES256_GCM:
     721         216 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
     722         216 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     723         216 :                 use_encryptv2 = true;
     724         216 :                 break;
     725           0 :         default:
     726           0 :                 return NT_STATUS_INVALID_PARAMETER;
     727             :         }
     728             : 
     729       14767 :         key_size = gnutls_cipher_get_key_size(algo);
     730       14767 :         tag_size = gnutls_cipher_get_tag_size(algo);
     731             : 
     732       14767 :         if (key_size != encryption_key->blob.length) {
     733           0 :                 return NT_STATUS_INTERNAL_ERROR;
     734             :         }
     735             : 
     736       14767 :         if (tag_size != 16) {
     737           0 :                 return NT_STATUS_INTERNAL_ERROR;
     738             :         }
     739             : 
     740       14767 :         key = (gnutls_datum_t) {
     741       14767 :                 .data = encryption_key->blob.data,
     742             :                 .size = key_size,
     743             :         };
     744             : 
     745       14767 :         iv = (gnutls_datum_t) {
     746       14767 :                 .data = tf + SMB2_TF_NONCE,
     747             :                 .size = iv_size,
     748             :         };
     749             : 
     750       14767 :         if (encryption_key->cipher_hnd == NULL) {
     751        7967 :                 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
     752             :                                         algo,
     753             :                                         &key);
     754        7967 :                 if (rc < 0) {
     755           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     756           0 :                         goto out;
     757             :                 }
     758             :         }
     759             : 
     760       14767 :         memset(tf + SMB2_TF_NONCE + iv_size,
     761             :                0,
     762       14767 :                16 - iv_size);
     763             : 
     764       14767 :         if (use_encryptv2) {
     765       14767 :                 uint8_t tag[tag_size];
     766         990 :                 giovec_t auth_iov[1];
     767             : 
     768       14767 :                 auth_iov[0] = (giovec_t) {
     769       13777 :                         .iov_base = tf + SMB2_TF_NONCE,
     770             :                         .iov_len  = a_total,
     771             :                 };
     772             : 
     773       14767 :                 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
     774       13777 :                                                   iv.data,
     775       13777 :                                                   iv.size,
     776             :                                                   auth_iov,
     777             :                                                   1,
     778       13777 :                                                   &vector[1],
     779             :                                                   count - 1,
     780             :                                                   tag,
     781             :                                                   &tag_size);
     782       14767 :                 if (rc < 0) {
     783           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     784           0 :                         goto out;
     785             :                 }
     786             : 
     787       14767 :                 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
     788             :         } else
     789             :         {
     790           0 :                 size_t ptext_size = m_total;
     791           0 :                 uint8_t *ptext = NULL;
     792           0 :                 size_t ctext_size = m_total + tag_size;
     793           0 :                 uint8_t *ctext = NULL;
     794           0 :                 size_t len = 0;
     795             :                 int i;
     796           0 :                 TALLOC_CTX *tmp_ctx = NULL;
     797             : 
     798             :                 /*
     799             :                  * If we come from python bindings, we don't have a stackframe
     800             :                  * around, so use the NULL context.
     801             :                  *
     802             :                  * This is fine as we make sure we free the memory.
     803             :                  */
     804           0 :                 if (talloc_stackframe_exists()) {
     805           0 :                         tmp_ctx = talloc_tos();
     806             :                 }
     807             : 
     808           0 :                 ptext = talloc_size(tmp_ctx, ptext_size);
     809           0 :                 if (ptext == NULL) {
     810           0 :                         status = NT_STATUS_NO_MEMORY;
     811           0 :                         goto out;
     812             :                 }
     813             : 
     814           0 :                 ctext = talloc_size(tmp_ctx, ctext_size);
     815           0 :                 if (ctext == NULL) {
     816           0 :                         TALLOC_FREE(ptext);
     817           0 :                         status = NT_STATUS_NO_MEMORY;
     818           0 :                         goto out;
     819             :                 }
     820             : 
     821           0 :                 for (i = 1; i < count; i++) {
     822           0 :                         if (vector[i].iov_base != NULL) {
     823           0 :                                 memcpy(ptext + len,
     824           0 :                                        vector[i].iov_base,
     825           0 :                                        vector[i].iov_len);
     826             :                         }
     827             : 
     828           0 :                         len += vector[i].iov_len;
     829           0 :                         if (len > ptext_size) {
     830           0 :                                 TALLOC_FREE(ptext);
     831           0 :                                 TALLOC_FREE(ctext);
     832           0 :                                 status = NT_STATUS_INTERNAL_ERROR;
     833           0 :                                 goto out;
     834             :                         }
     835             :                 }
     836             : 
     837           0 :                 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
     838           0 :                                                 iv.data,
     839           0 :                                                 iv.size,
     840           0 :                                                 tf + SMB2_TF_NONCE,
     841             :                                                 a_total,
     842             :                                                 tag_size,
     843             :                                                 ptext,
     844             :                                                 ptext_size,
     845             :                                                 ctext,
     846             :                                                 &ctext_size);
     847           0 :                 if (rc < 0 || ctext_size != m_total + tag_size) {
     848           0 :                         TALLOC_FREE(ptext);
     849           0 :                         TALLOC_FREE(ctext);
     850           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     851           0 :                         goto out;
     852             :                 }
     853             : 
     854           0 :                 len = 0;
     855           0 :                 for (i = 1; i < count; i++) {
     856           0 :                         if (vector[i].iov_base != NULL) {
     857           0 :                                 memcpy(vector[i].iov_base,
     858           0 :                                        ctext + len,
     859           0 :                                        vector[i].iov_len);
     860             :                         }
     861             : 
     862           0 :                         len += vector[i].iov_len;
     863             :                 }
     864             : 
     865           0 :                 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
     866             : 
     867           0 :                 TALLOC_FREE(ptext);
     868           0 :                 TALLOC_FREE(ctext);
     869             :         }
     870             : 
     871       14767 :         DBG_INFO("Encrypted SMB2 message\n");
     872             : 
     873       13777 :         status = NT_STATUS_OK;
     874       14767 : out:
     875       14767 :         return status;
     876             : }
     877             : 
     878       14752 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
     879             :                                   struct iovec *vector,
     880             :                                   int count)
     881             : {
     882       14752 :         bool use_encryptv2 = false;
     883         990 :         uint16_t cipher_id;
     884         990 :         uint8_t *tf;
     885         990 :         uint16_t flags;
     886         990 :         size_t a_total;
     887         990 :         ssize_t m_total;
     888       14752 :         uint32_t msg_size = 0;
     889       14752 :         uint32_t iv_size = 0;
     890       14752 :         uint32_t key_size = 0;
     891       14752 :         size_t tag_size = 0;
     892       14752 :         gnutls_cipher_algorithm_t algo = 0;
     893         990 :         gnutls_datum_t key;
     894         990 :         gnutls_datum_t iv;
     895         990 :         NTSTATUS status;
     896         990 :         int rc;
     897             : 
     898       14752 :         if (count < 1) {
     899           0 :                 return NT_STATUS_INVALID_PARAMETER;
     900             :         }
     901             : 
     902       14752 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
     903           0 :                 return NT_STATUS_INVALID_PARAMETER;
     904             :         }
     905             : 
     906       14752 :         tf = (uint8_t *)vector[0].iov_base;
     907             : 
     908       14752 :         if (!smb2_signing_key_valid(decryption_key)) {
     909           0 :                 DBG_WARNING("No decryption key for SMB2 signing\n");
     910           0 :                 return NT_STATUS_ACCESS_DENIED;
     911             :         }
     912       14752 :         cipher_id = decryption_key->cipher_algo_id;
     913             : 
     914       14752 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
     915             : 
     916       14752 :         m_total = iov_buflen(&vector[1], count-1);
     917       14752 :         if (m_total == -1) {
     918           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     919             :         }
     920             : 
     921       14752 :         flags = SVAL(tf, SMB2_TF_FLAGS);
     922       14752 :         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
     923             : 
     924       14752 :         if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
     925           0 :                 return NT_STATUS_ACCESS_DENIED;
     926             :         }
     927             : 
     928       14752 :         if (msg_size != m_total) {
     929           0 :                 return NT_STATUS_INTERNAL_ERROR;
     930             :         }
     931             : 
     932       14752 :         switch (cipher_id) {
     933        1116 :         case SMB2_ENCRYPTION_AES128_CCM:
     934        1116 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
     935        1116 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     936             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     937        1116 :                 use_encryptv2 = true;
     938             : #endif
     939        1116 :                 break;
     940       12992 :         case SMB2_ENCRYPTION_AES128_GCM:
     941       12992 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
     942       12992 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     943       12992 :                 use_encryptv2 = true;
     944       12992 :                 break;
     945         216 :         case SMB2_ENCRYPTION_AES256_CCM:
     946         216 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
     947         216 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     948             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     949         216 :                 use_encryptv2 = true;
     950             : #endif
     951         216 :                 break;
     952         216 :         case SMB2_ENCRYPTION_AES256_GCM:
     953         216 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
     954         216 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     955         216 :                 use_encryptv2 = true;
     956         216 :                 break;
     957           0 :         default:
     958           0 :                 return NT_STATUS_INVALID_PARAMETER;
     959             :         }
     960             : 
     961       14752 :         key_size = gnutls_cipher_get_key_size(algo);
     962       14752 :         tag_size = gnutls_cipher_get_tag_size(algo);
     963             : 
     964       14752 :         if (key_size != decryption_key->blob.length) {
     965           0 :                 return NT_STATUS_INTERNAL_ERROR;
     966             :         }
     967             : 
     968       14752 :         if (tag_size != 16) {
     969           0 :                 return NT_STATUS_INTERNAL_ERROR;
     970             :         }
     971             : 
     972       14752 :         key = (gnutls_datum_t) {
     973       14752 :                 .data = decryption_key->blob.data,
     974             :                 .size = key_size,
     975             :         };
     976             : 
     977       14752 :         iv = (gnutls_datum_t) {
     978       14752 :                 .data = tf + SMB2_TF_NONCE,
     979             :                 .size = iv_size,
     980             :         };
     981             : 
     982       14752 :         if (decryption_key->cipher_hnd == NULL) {
     983        1343 :                 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
     984             :                                              algo,
     985             :                                              &key);
     986        1343 :                 if (rc < 0) {
     987           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     988           0 :                         goto out;
     989             :                 }
     990             :         }
     991             : 
     992       14752 :         if (use_encryptv2) {
     993         990 :                 giovec_t auth_iov[1];
     994             : 
     995       14752 :                 auth_iov[0] = (giovec_t) {
     996       13762 :                         .iov_base = tf + SMB2_TF_NONCE,
     997             :                         .iov_len  = a_total,
     998             :                 };
     999             : 
    1000       15742 :                 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
    1001       13762 :                                                   iv.data,
    1002       13762 :                                                   iv.size,
    1003             :                                                   auth_iov,
    1004             :                                                   1,
    1005       13762 :                                                   &vector[1],
    1006             :                                                   count - 1,
    1007       14752 :                                                   tf + SMB2_TF_SIGNATURE,
    1008             :                                                   tag_size);
    1009       14752 :                 if (rc < 0) {
    1010           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1011           0 :                         goto out;
    1012             :                 }
    1013             :         } else
    1014             :         {
    1015           0 :                 size_t ctext_size = m_total + tag_size;
    1016           0 :                 uint8_t *ctext = NULL;
    1017           0 :                 size_t ptext_size = m_total;
    1018           0 :                 uint8_t *ptext = NULL;
    1019           0 :                 size_t len = 0;
    1020             :                 int i;
    1021           0 :                 TALLOC_CTX *tmp_ctx = NULL;
    1022             : 
    1023             :                 /*
    1024             :                  * If we come from python bindings, we don't have a stackframe
    1025             :                  * around, so use the NULL context.
    1026             :                  *
    1027             :                  * This is fine as we make sure we free the memory.
    1028             :                  */
    1029           0 :                 if (talloc_stackframe_exists()) {
    1030           0 :                         tmp_ctx = talloc_tos();
    1031             :                 }
    1032             : 
    1033             :                 /* GnuTLS doesn't have a iovec API for decryption yet */
    1034             : 
    1035           0 :                 ptext = talloc_size(tmp_ctx, ptext_size);
    1036           0 :                 if (ptext == NULL) {
    1037           0 :                         status = NT_STATUS_NO_MEMORY;
    1038           0 :                         goto out;
    1039             :                 }
    1040             : 
    1041           0 :                 ctext = talloc_size(tmp_ctx, ctext_size);
    1042           0 :                 if (ctext == NULL) {
    1043           0 :                         TALLOC_FREE(ptext);
    1044           0 :                         status = NT_STATUS_NO_MEMORY;
    1045           0 :                         goto out;
    1046             :                 }
    1047             : 
    1048             : 
    1049           0 :                 for (i = 1; i < count; i++) {
    1050           0 :                         memcpy(ctext + len,
    1051           0 :                                vector[i].iov_base,
    1052           0 :                                vector[i].iov_len);
    1053             : 
    1054           0 :                         len += vector[i].iov_len;
    1055             :                 }
    1056           0 :                 if (len != m_total) {
    1057           0 :                         TALLOC_FREE(ptext);
    1058           0 :                         TALLOC_FREE(ctext);
    1059           0 :                         status = NT_STATUS_INTERNAL_ERROR;
    1060           0 :                         goto out;
    1061             :                 }
    1062             : 
    1063           0 :                 memcpy(ctext + len,
    1064           0 :                        tf + SMB2_TF_SIGNATURE,
    1065             :                        tag_size);
    1066             : 
    1067             :                 /* This function will verify the tag */
    1068           0 :                 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
    1069           0 :                                                 iv.data,
    1070           0 :                                                 iv.size,
    1071           0 :                                                 tf + SMB2_TF_NONCE,
    1072             :                                                 a_total,
    1073             :                                                 tag_size,
    1074             :                                                 ctext,
    1075             :                                                 ctext_size,
    1076             :                                                 ptext,
    1077             :                                                 &ptext_size);
    1078           0 :                 if (rc < 0) {
    1079           0 :                         TALLOC_FREE(ptext);
    1080           0 :                         TALLOC_FREE(ctext);
    1081           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1082           0 :                         goto out;
    1083             :                 }
    1084           0 :                 if (ptext_size != m_total) {
    1085           0 :                         TALLOC_FREE(ptext);
    1086           0 :                         TALLOC_FREE(ctext);
    1087           0 :                         rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
    1088           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1089           0 :                         goto out;
    1090             :                 }
    1091             : 
    1092           0 :                 len = 0;
    1093           0 :                 for (i = 1; i < count; i++) {
    1094           0 :                         memcpy(vector[i].iov_base,
    1095           0 :                                ptext + len,
    1096           0 :                                vector[i].iov_len);
    1097             : 
    1098           0 :                         len += vector[i].iov_len;
    1099             :                 }
    1100             : 
    1101           0 :                 TALLOC_FREE(ptext);
    1102           0 :                 TALLOC_FREE(ctext);
    1103             :         }
    1104             : 
    1105       14752 :         DBG_INFO("Decrypted SMB2 message\n");
    1106             : 
    1107       13762 :         status = NT_STATUS_OK;
    1108       14752 : out:
    1109       14752 :         return status;
    1110             : }

Generated by: LCOV version 1.14