LCOV - code coverage report
Current view: top level - libcli/smb - smb2_signing.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 446 641 69.6 %
Date: 2023-11-21 12:31:41 Functions: 14 14 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       48147 : 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       48147 :         *ds = (struct smb2_signing_derivations) { .signing = NULL, };
      37             : 
      38       48147 :         if (protocol >= PROTOCOL_SMB3_11) {
      39       41601 :                 struct smb2_signing_derivation *d = NULL;
      40             : 
      41       41601 :                 SMB_ASSERT(preauth_hash.length != 0);
      42             : 
      43       41601 :                 d = &ds->__signing;
      44       41601 :                 ds->signing = d;
      45       41601 :                 d->label = data_blob_string_const_null("SMBSigningKey");
      46       41601 :                 d->context = preauth_hash;
      47             : 
      48       41601 :                 d = &ds->__cipher_c2s;
      49       41601 :                 ds->cipher_c2s = d;
      50       41601 :                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
      51       41601 :                 d->context = preauth_hash;
      52             : 
      53       41601 :                 d = &ds->__cipher_s2c;
      54       41601 :                 ds->cipher_s2c = d;
      55       41601 :                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
      56       41601 :                 d->context = preauth_hash;
      57             : 
      58       41601 :                 d = &ds->__application;
      59       41601 :                 ds->application = d;
      60       41601 :                 d->label = data_blob_string_const_null("SMBAppKey");
      61       41601 :                 d->context = preauth_hash;
      62             : 
      63        6546 :         } 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       48147 : }
      87             : 
      88      320135 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
      89             : {
      90      320135 :         if (key->hmac_hnd != NULL) {
      91        7777 :                 gnutls_hmac_deinit(key->hmac_hnd, NULL);
      92        7777 :                 key->hmac_hnd = NULL;
      93             :         }
      94             : 
      95      320135 :         if (key->cipher_hnd != NULL) {
      96       48452 :                 gnutls_aead_cipher_deinit(key->cipher_hnd);
      97       48452 :                 key->cipher_hnd = NULL;
      98             :         }
      99             : 
     100      320135 :         return 0;
     101             : }
     102             : 
     103       54532 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
     104             :                                const struct smb2_signing_key *src,
     105             :                                struct smb2_signing_key **_dst)
     106             : {
     107       54532 :         struct smb2_signing_key *dst = NULL;
     108             : 
     109       54532 :         dst = talloc_zero(mem_ctx, struct smb2_signing_key);
     110       54532 :         if (dst == NULL) {
     111           0 :                 return NT_STATUS_NO_MEMORY;
     112             :         }
     113       54532 :         talloc_set_destructor(dst, smb2_signing_key_destructor);
     114             : 
     115       54532 :         dst->sign_algo_id = src->sign_algo_id;
     116       54532 :         dst->cipher_algo_id = src->cipher_algo_id;
     117             : 
     118       54532 :         if (src->blob.length == 0) {
     119           0 :                 *_dst = dst;
     120           0 :                 return NT_STATUS_OK;
     121             :         }
     122             : 
     123       54532 :         dst->blob = data_blob_talloc_zero(dst, src->blob.length);
     124       54532 :         if (dst->blob.length == 0) {
     125           0 :                 TALLOC_FREE(dst);
     126           0 :                 return NT_STATUS_NO_MEMORY;
     127             :         }
     128       54532 :         talloc_keep_secret(dst->blob.data);
     129       54532 :         memcpy(dst->blob.data, src->blob.data, dst->blob.length);
     130             : 
     131       54532 :         *_dst = dst;
     132       54532 :         return NT_STATUS_OK;
     133             : }
     134             : 
     135      295126 : 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      295126 :         struct smb2_signing_key *key = NULL;
     143      295126 :         size_t in_key_length = 16;
     144      295126 :         size_t out_key_length = 16;
     145        7597 :         NTSTATUS status;
     146             : 
     147      295126 :         if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
     148      206209 :                 SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
     149             :         }
     150      295126 :         if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
     151       88917 :                 SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
     152             :         }
     153             : 
     154      295126 :         key = talloc_zero(mem_ctx, struct smb2_signing_key);
     155      295126 :         if (key == NULL) {
     156           0 :                 return NT_STATUS_NO_MEMORY;
     157             :         }
     158      295126 :         talloc_set_destructor(key, smb2_signing_key_destructor);
     159             : 
     160      295126 :         key->sign_algo_id = sign_algo_id;
     161      295126 :         key->cipher_algo_id = cipher_algo_id;
     162             : 
     163      295126 :         if (master_key == NULL) {
     164      106436 :                 SMB_ASSERT(d == NULL);
     165             : 
     166      106436 :                 *_key = key;
     167      106436 :                 return NT_STATUS_OK;
     168             :         }
     169             : 
     170             :         /*
     171             :          * Per default use the full key.
     172             :          */
     173      188690 :         in_key_length = out_key_length = master_key->length;
     174      188690 :         switch (sign_algo_id) {
     175       85296 :         case SMB2_SIGNING_INVALID_ALGO:
     176             :                 /*
     177             :                  * This means we're processing cipher_algo_id below
     178             :                  */
     179       85296 :                 break;
     180        5540 :         case SMB2_SIGNING_MD5_SMB1:
     181        5540 :                 SMB_ASSERT(d == NULL);
     182        5407 :                 break;
     183       95390 :         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       95390 :                 in_key_length = out_key_length = 16;
     194       95390 :                 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      188690 :         switch (cipher_algo_id) {
     200       98283 :         case SMB2_ENCRYPTION_INVALID_ALGO:
     201             :                 /*
     202             :                  * This means we're processing sign_algo_id above
     203             :                  */
     204       98283 :                 break;
     205        8224 :         case SMB2_ENCRYPTION_NONE:
     206             :                 /*
     207             :                  * No encryption negotiated.
     208             :                  */
     209        8224 :                 break;
     210       79412 :         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       79412 :                 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       76992 :                 in_key_length = out_key_length = 16;
     222       76992 :                 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      186254 :         if (out_key_length == 0) {
     242           0 :                 *_key = key;
     243           0 :                 return NT_STATUS_OK;
     244             :         }
     245             : 
     246      188690 :         key->blob = data_blob_talloc_zero(key, out_key_length);
     247      188690 :         if (key->blob.length == 0) {
     248           0 :                 TALLOC_FREE(key);
     249           0 :                 return NT_STATUS_NO_MEMORY;
     250             :         }
     251      188690 :         talloc_keep_secret(key->blob.data);
     252      188690 :         memcpy(key->blob.data,
     253      188690 :                master_key->data,
     254      188690 :                MIN(key->blob.length, master_key->length));
     255             : 
     256      188690 :         if (d == NULL) {
     257       26178 :                 *_key = key;
     258       26178 :                 return NT_STATUS_OK;
     259             :         }
     260             : 
     261      162512 :         status = smb2_key_derivation(key->blob.data, in_key_length,
     262      162512 :                                      d->label.data, d->label.length,
     263      162512 :                                      d->context.data, d->context.length,
     264             :                                      key->blob.data, out_key_length);
     265      162512 :         if (!NT_STATUS_IS_OK(status)) {
     266           0 :                 TALLOC_FREE(key);
     267           0 :                 return status;
     268             :         }
     269             : 
     270      162512 :         *_key = key;
     271      162512 :         return NT_STATUS_OK;
     272             : }
     273             : 
     274      206209 : NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
     275             :                                       uint16_t sign_algo_id,
     276             :                                       const DATA_BLOB *master_key,
     277             :                                       const struct smb2_signing_derivation *d,
     278             :                                       struct smb2_signing_key **_key)
     279             : {
     280      206209 :         return smb2_signing_key_create(mem_ctx,
     281             :                                        sign_algo_id,
     282             :                                        SMB2_ENCRYPTION_INVALID_ALGO,
     283             :                                        master_key,
     284             :                                        d,
     285             :                                        _key);
     286             : }
     287             : 
     288       88917 : NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
     289             :                                         uint16_t cipher_algo_id,
     290             :                                         const DATA_BLOB *master_key,
     291             :                                         const struct smb2_signing_derivation *d,
     292             :                                         struct smb2_signing_key **_key)
     293             : {
     294       88917 :         return smb2_signing_key_create(mem_ctx,
     295             :                                        SMB2_SIGNING_INVALID_ALGO,
     296             :                                        cipher_algo_id,
     297             :                                        master_key,
     298             :                                        d,
     299             :                                        _key);
     300             : }
     301             : 
     302    10393310 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
     303             : {
     304    10393310 :         if (key == NULL) {
     305      785057 :                 return false;
     306             :         }
     307             : 
     308     9604775 :         if (key->blob.length == 0 || key->blob.data == NULL) {
     309      284963 :                 return false;
     310             :         }
     311             : 
     312     9212656 :         return true;
     313             : }
     314             : 
     315     2548563 : static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd,
     316             :                                   const uint8_t *iv, size_t iv_size,
     317             :                                   const giovec_t *auth_iov, uint8_t auth_iovcnt,
     318             :                                   uint8_t *tag, size_t _tag_size)
     319             : {
     320     2548563 :         size_t tag_size = _tag_size;
     321       39316 :         int rc;
     322             : 
     323     2548563 :         rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
     324             :                                           iv, iv_size,
     325             :                                           auth_iov, auth_iovcnt,
     326             :                                           NULL, 0,
     327             :                                           tag, &tag_size);
     328     2548563 :         if (rc < 0) {
     329           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     330             :         }
     331             : 
     332     2548563 :         return NT_STATUS_OK;
     333             : }
     334             : 
     335     3669953 : static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
     336             :                                             uint16_t sign_algo_id,
     337             :                                             const struct iovec *vector,
     338             :                                             int count,
     339             :                                             uint8_t signature[16])
     340             : {
     341     3669953 :         const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
     342       40770 :         uint16_t opcode;
     343       40770 :         uint32_t flags;
     344       40770 :         uint64_t msg_id;
     345       40770 :         static const uint8_t zero_sig[16] = { 0, };
     346     3669953 :         gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
     347       40770 :         int i;
     348             : 
     349             :         /*
     350             :          * We expect
     351             :          * - SMB2 HDR
     352             :          * - SMB2 BODY FIXED
     353             :          * - (optional) SMB2 BODY DYN
     354             :          * - (optional) PADDING
     355             :          */
     356     3669953 :         SMB_ASSERT(count >= 2);
     357     3669953 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     358     3669953 :         SMB_ASSERT(count <= 4);
     359             : 
     360     3669953 :         opcode = SVAL(hdr, SMB2_HDR_OPCODE);
     361     3669953 :         flags = IVAL(hdr, SMB2_HDR_FLAGS);
     362     3669953 :         if (flags & SMB2_HDR_FLAG_REDIRECT) {
     363     1854227 :                 NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
     364     1854227 :                 if (NT_STATUS_EQUAL(pdu_status, NT_STATUS_PENDING)) {
     365           0 :                         DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode);
     366           0 :                         return NT_STATUS_INTERNAL_ERROR;
     367             :                 }
     368     1854227 :                 if (opcode == SMB2_OP_CANCEL) {
     369           0 :                         DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
     370           0 :                         return NT_STATUS_INTERNAL_ERROR;
     371             :                 }
     372             :         }
     373     3669953 :         msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
     374     3669953 :         if (msg_id == 0) {
     375          42 :                 if (opcode != SMB2_OP_CANCEL ||
     376           8 :                     sign_algo_id >= SMB2_SIGNING_AES128_GMAC)
     377             :                 {
     378           0 :                         DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
     379           0 :                         return NT_STATUS_INTERNAL_ERROR;
     380             :                 }
     381             :                 /*
     382             :                  * Legacy algorithms allow MID 0
     383             :                  * for cancel requests
     384             :                  */
     385             :         }
     386     3669953 :         if (msg_id == UINT64_MAX) {
     387           0 :                 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
     388           0 :                 return NT_STATUS_INTERNAL_ERROR;
     389             :         }
     390             : 
     391     3669953 :         switch (sign_algo_id) {
     392     2548563 :         case SMB2_SIGNING_AES128_GMAC: {
     393     2548563 :                 gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
     394     2548563 :                 uint32_t key_size = gnutls_cipher_get_key_size(algo);
     395     2548563 :                 uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
     396     2548563 :                 size_t tag_size = gnutls_cipher_get_tag_size(algo);
     397     2548563 :                 gnutls_datum_t key = {
     398     2548563 :                         .data = signing_key->blob.data,
     399     2548563 :                         .size = MIN(signing_key->blob.length, key_size),
     400             :                 };
     401     2548563 :                 uint64_t high_bits = 0;
     402     2548563 :                 uint8_t iv[AES_BLOCK_SIZE] = {0};
     403     2548563 :                 giovec_t auth_iov[count+1];
     404     2548563 :                 size_t auth_iovcnt = 0;
     405       39316 :                 NTSTATUS status;
     406       39316 :                 int rc;
     407             : 
     408     2548563 :                 high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
     409     2548563 :                 if (opcode == SMB2_OP_CANCEL) {
     410          38 :                         high_bits |= SMB2_HDR_FLAG_ASYNC;
     411             :                 }
     412     2548563 :                 SBVAL(iv, 0, msg_id);
     413     2548563 :                 SBVAL(iv, 8, high_bits);
     414             : 
     415     2548563 :                 if (signing_key->cipher_hnd == NULL) {
     416       42464 :                         rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
     417             :                                                      algo,
     418             :                                                      &key);
     419       42464 :                         if (rc < 0) {
     420           0 :                                 return gnutls_error_to_ntstatus(rc,
     421             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     422             :                         }
     423             :                 }
     424             : 
     425     2548563 :                 SMB_ASSERT(key_size == 16);
     426     2548563 :                 SMB_ASSERT(iv_size == 12);
     427     2548563 :                 SMB_ASSERT(tag_size == 16);
     428             : 
     429     2548563 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     430             :                         .iov_base = discard_const_p(uint8_t, hdr),
     431             :                         .iov_len  = SMB2_HDR_SIGNATURE,
     432             :                 };
     433     2548563 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     434             :                         .iov_base = discard_const_p(uint8_t, zero_sig),
     435             :                         .iov_len  = 16,
     436             :                 };
     437     7625307 :                 for (i=1; i < count; i++) {
     438     5076744 :                         auth_iov[auth_iovcnt++] = (giovec_t) {
     439     5076744 :                                 .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
     440     5076744 :                                 .iov_len  = vector[i].iov_len,
     441             :                         };
     442             :                 }
     443             : 
     444     2548563 :                 status = smb2_signing_gmac(signing_key->cipher_hnd,
     445             :                                            iv,
     446             :                                            iv_size,
     447             :                                            auth_iov,
     448             :                                            auth_iovcnt,
     449             :                                            signature,
     450             :                                            tag_size);
     451     2548563 :                 if (!NT_STATUS_IS_OK(status)) {
     452           0 :                         return status;
     453             :                 }
     454             : 
     455     2548563 :                 return NT_STATUS_OK;
     456             :         }       break;
     457             : 
     458        2978 :         case SMB2_SIGNING_AES128_CMAC:
     459        2978 :                 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
     460        2978 :                 break;
     461     1117802 :         case SMB2_SIGNING_HMAC_SHA256:
     462     1117802 :                 hmac_algo = GNUTLS_MAC_SHA256;
     463     1117802 :                 break;
     464             : 
     465           0 :         default:
     466           0 :                 return NT_STATUS_HMAC_NOT_SUPPORTED;
     467             :         }
     468             : 
     469     1121390 :         if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
     470     1121390 :                 uint8_t digest[gnutls_hash_get_len(hmac_algo)];
     471     1121390 :                 gnutls_datum_t key = {
     472     1121390 :                         .data = signing_key->blob.data,
     473     1121390 :                         .size = MIN(signing_key->blob.length, 16),
     474             :                 };
     475        1454 :                 int rc;
     476             : 
     477     1121390 :                 if (signing_key->hmac_hnd == NULL) {
     478        7821 :                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
     479             :                                               hmac_algo,
     480        7541 :                                               key.data,
     481        7541 :                                               key.size);
     482        7821 :                         if (rc < 0) {
     483           0 :                                 return gnutls_error_to_ntstatus(rc,
     484             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     485             :                         }
     486             :                 }
     487             : 
     488     1121390 :                 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
     489     1121390 :                 if (rc < 0) {
     490           0 :                         return gnutls_error_to_ntstatus(rc,
     491             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     492             :                 }
     493     1121390 :                 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
     494     1121390 :                 if (rc < 0) {
     495           0 :                         return gnutls_error_to_ntstatus(rc,
     496             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     497             :                 }
     498             : 
     499     3351467 :                 for (i = 1; i < count; i++) {
     500     2232981 :                         rc = gnutls_hmac(signing_key->hmac_hnd,
     501     2230077 :                                          vector[i].iov_base,
     502     2230077 :                                          vector[i].iov_len);
     503     2230077 :                         if (rc < 0) {
     504           0 :                                 return gnutls_error_to_ntstatus(rc,
     505             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     506             :                         }
     507             :                 }
     508     1121390 :                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
     509     1121390 :                 memcpy(signature, digest, 16);
     510     1121390 :                 ZERO_ARRAY(digest);
     511     1121390 :                 return NT_STATUS_OK;
     512             :         }
     513             : 
     514           0 :         return NT_STATUS_HMAC_NOT_SUPPORTED;
     515             : }
     516             : 
     517     1838161 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
     518             :                                struct iovec *vector,
     519             :                                int count)
     520             : {
     521       20723 :         uint16_t sign_algo_id;
     522       20723 :         uint8_t *hdr;
     523       20723 :         uint64_t session_id;
     524       20723 :         uint8_t res[16];
     525       20723 :         NTSTATUS status;
     526             : 
     527             :         /*
     528             :          * We expect
     529             :          * - SMB2 HDR
     530             :          * - SMB2 BODY FIXED
     531             :          * - (optional) SMB2 BODY DYN
     532             :          * - (optional) PADDING
     533             :          */
     534     1838161 :         SMB_ASSERT(count >= 2);
     535     1838161 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     536     1838161 :         SMB_ASSERT(count <= 4);
     537             : 
     538     1838161 :         hdr = (uint8_t *)vector[0].iov_base;
     539             : 
     540     1838161 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     541     1838161 :         if (session_id == 0) {
     542             :                 /*
     543             :                  * do not sign messages with a zero session_id.
     544             :                  * See MS-SMB2 3.2.4.1.1
     545             :                  */
     546           0 :                 return NT_STATUS_OK;
     547             :         }
     548             : 
     549     1838161 :         if (!smb2_signing_key_valid(signing_key)) {
     550           0 :                 DBG_WARNING("No signing key for SMB2 signing\n");
     551           0 :                 return NT_STATUS_ACCESS_DENIED;
     552             :         }
     553             : 
     554     1838161 :         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
     555             : 
     556     1838161 :         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
     557             : 
     558     1838161 :         sign_algo_id = signing_key->sign_algo_id;
     559             : 
     560     1838161 :         status = smb2_signing_calc_signature(signing_key,
     561             :                                              sign_algo_id,
     562             :                                              vector,
     563             :                                              count,
     564             :                                              res);
     565     1838161 :         if (!NT_STATUS_IS_OK(status)) {
     566           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     567             :                         (unsigned)sign_algo_id, nt_errstr(status));
     568           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     569           0 :                         smb_panic(__location__);
     570             :                 }
     571           0 :                 return status;
     572             :         }
     573             : 
     574     1838161 :         DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
     575             :                  (unsigned)sign_algo_id));
     576             : 
     577     1838161 :         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
     578             : 
     579     1838161 :         return NT_STATUS_OK;
     580             : }
     581             : 
     582     1831792 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
     583             :                                 const struct iovec *vector,
     584             :                                 int count)
     585             : {
     586       20047 :         uint16_t sign_algo_id;
     587       20047 :         const uint8_t *hdr;
     588       20047 :         const uint8_t *sig;
     589       20047 :         uint64_t session_id;
     590       20047 :         uint8_t res[16];
     591       20047 :         NTSTATUS status;
     592             : 
     593             :         /*
     594             :          * We expect
     595             :          * - SMB2 HDR
     596             :          * - SMB2 BODY FIXED
     597             :          * - (optional) SMB2 BODY DYN
     598             :          * - (optional) PADDING
     599             :          */
     600     1831792 :         SMB_ASSERT(count >= 2);
     601     1831792 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     602     1831792 :         SMB_ASSERT(count <= 4);
     603             : 
     604     1831792 :         hdr = (const uint8_t *)vector[0].iov_base;
     605             : 
     606     1831792 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     607     1831792 :         if (session_id == 0) {
     608             :                 /*
     609             :                  * do not sign messages with a zero session_id.
     610             :                  * See MS-SMB2 3.2.4.1.1
     611             :                  */
     612           0 :                 return NT_STATUS_OK;
     613             :         }
     614             : 
     615     1831792 :         if (!smb2_signing_key_valid(signing_key)) {
     616             :                 /* we don't have the session key yet */
     617           0 :                 return NT_STATUS_OK;
     618             :         }
     619             : 
     620     1831792 :         sig = hdr+SMB2_HDR_SIGNATURE;
     621             : 
     622     1831792 :         sign_algo_id = signing_key->sign_algo_id;
     623             : 
     624     1831792 :         status = smb2_signing_calc_signature(signing_key,
     625             :                                              sign_algo_id,
     626             :                                              vector,
     627             :                                              count,
     628             :                                              res);
     629     1831792 :         if (!NT_STATUS_IS_OK(status)) {
     630           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     631             :                         (unsigned)sign_algo_id, nt_errstr(status));
     632           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     633           0 :                         status = NT_STATUS_ACCESS_DENIED;
     634             :                 }
     635           0 :                 return status;
     636             :         }
     637             : 
     638     1831792 :         if (!mem_equal_const_time(res, sig, 16)) {
     639         256 :                 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
     640             :                          (unsigned)sign_algo_id));
     641         256 :                 dump_data(0, sig, 16);
     642         256 :                 dump_data(0, res, 16);
     643         256 :                 return NT_STATUS_ACCESS_DENIED;
     644             :         }
     645             : 
     646     1831536 :         return NT_STATUS_OK;
     647             : }
     648             : 
     649      163462 : NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
     650             :                              const uint8_t *Label, size_t Label_len,
     651             :                              const uint8_t *Context, size_t Context_len,
     652             :                              uint8_t *KO, size_t KO_len)
     653      163462 : {
     654      163462 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     655        4912 :         uint8_t buf[4];
     656        4912 :         static const uint8_t zero = 0;
     657      163462 :         const size_t digest_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
     658      163462 :         uint8_t digest[digest_len];
     659      163462 :         uint32_t i = 1;
     660      163462 :         uint32_t L = KO_len * 8;
     661        4912 :         int rc;
     662             : 
     663      163462 :         if (KO_len > digest_len) {
     664           0 :                 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len, digest_len);
     665           0 :                 return NT_STATUS_INTERNAL_ERROR;
     666             :         }
     667             : 
     668      163462 :         switch (KO_len) {
     669      158550 :         case 16:
     670             :         case 32:
     671      163462 :                 break;
     672           0 :         default:
     673           0 :                 DBG_ERR("KO_len[%zu] not supported\n", KO_len);
     674           0 :                 return NT_STATUS_INTERNAL_ERROR;
     675             :         }
     676             : 
     677             :         /*
     678             :          * a simplified version of
     679             :          * "NIST Special Publication 800-108" section 5.1
     680             :          * using hmac-sha256.
     681             :          */
     682      163462 :         rc = gnutls_hmac_init(&hmac_hnd,
     683             :                               GNUTLS_MAC_SHA256,
     684             :                               KI,
     685             :                               KI_len);
     686      163462 :         if (rc < 0) {
     687           0 :                 return gnutls_error_to_ntstatus(rc,
     688             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     689             :         }
     690             : 
     691      163462 :         RSIVAL(buf, 0, i);
     692      163462 :         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
     693      163462 :         if (rc < 0) {
     694           0 :                 return gnutls_error_to_ntstatus(rc,
     695             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     696             :         }
     697      163462 :         rc = gnutls_hmac(hmac_hnd, Label, Label_len);
     698      163462 :         if (rc < 0) {
     699           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     700           0 :                 return gnutls_error_to_ntstatus(rc,
     701             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     702             :         }
     703      163462 :         rc = gnutls_hmac(hmac_hnd, &zero, 1);
     704      163462 :         if (rc < 0) {
     705           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     706           0 :                 return gnutls_error_to_ntstatus(rc,
     707             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     708             :         }
     709      163462 :         rc = gnutls_hmac(hmac_hnd, Context, Context_len);
     710      163462 :         if (rc < 0) {
     711           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     712           0 :                 return gnutls_error_to_ntstatus(rc,
     713             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     714             :         }
     715      163462 :         RSIVAL(buf, 0, L);
     716      163462 :         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
     717      163462 :         if (rc < 0) {
     718           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     719           0 :                 return gnutls_error_to_ntstatus(rc,
     720             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     721             :         }
     722             : 
     723      163462 :         gnutls_hmac_deinit(hmac_hnd, digest);
     724             : 
     725      163462 :         memcpy(KO, digest, KO_len);
     726             : 
     727      163462 :         ZERO_ARRAY(digest);
     728             : 
     729      163462 :         return NT_STATUS_OK;
     730             : }
     731             : 
     732       14558 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
     733             :                                   struct iovec *vector,
     734             :                                   int count)
     735             : {
     736       14558 :         bool use_encryptv2 = false;
     737         990 :         uint16_t cipher_id;
     738         990 :         uint8_t *tf;
     739         990 :         size_t a_total;
     740         990 :         ssize_t m_total;
     741       14558 :         uint32_t iv_size = 0;
     742       14558 :         uint32_t key_size = 0;
     743       14558 :         size_t tag_size = 0;
     744       14558 :         gnutls_cipher_algorithm_t algo = 0;
     745         990 :         gnutls_datum_t key;
     746         990 :         gnutls_datum_t iv;
     747         990 :         NTSTATUS status;
     748         990 :         int rc;
     749             : 
     750       14558 :         if (count < 1) {
     751           0 :                 return NT_STATUS_INVALID_PARAMETER;
     752             :         }
     753             : 
     754       14558 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
     755           0 :                 return NT_STATUS_INVALID_PARAMETER;
     756             :         }
     757             : 
     758       14558 :         tf = (uint8_t *)vector[0].iov_base;
     759             : 
     760       14558 :         if (!smb2_signing_key_valid(encryption_key)) {
     761           0 :                 DBG_WARNING("No encryption key for SMB2 signing\n");
     762           0 :                 return NT_STATUS_ACCESS_DENIED;
     763             :         }
     764       14558 :         cipher_id = encryption_key->cipher_algo_id;
     765             : 
     766       14558 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
     767             : 
     768       14558 :         m_total = iov_buflen(&vector[1], count-1);
     769       14558 :         if (m_total == -1) {
     770           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     771             :         }
     772             : 
     773       14558 :         SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
     774       14558 :         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
     775             : 
     776       14558 :         switch (cipher_id) {
     777        1116 :         case SMB2_ENCRYPTION_AES128_CCM:
     778        1116 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
     779        1116 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     780             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     781        1116 :                 use_encryptv2 = true;
     782             : #endif
     783        1116 :                 break;
     784       12798 :         case SMB2_ENCRYPTION_AES128_GCM:
     785       12798 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
     786       12798 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     787       12798 :                 use_encryptv2 = true;
     788       12798 :                 break;
     789         216 :         case SMB2_ENCRYPTION_AES256_CCM:
     790         216 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
     791         216 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     792             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     793         216 :                 use_encryptv2 = true;
     794             : #endif
     795         216 :                 break;
     796         216 :         case SMB2_ENCRYPTION_AES256_GCM:
     797         216 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
     798         216 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     799         216 :                 use_encryptv2 = true;
     800         216 :                 break;
     801           0 :         default:
     802           0 :                 return NT_STATUS_INVALID_PARAMETER;
     803             :         }
     804             : 
     805       14558 :         key_size = gnutls_cipher_get_key_size(algo);
     806       14558 :         tag_size = gnutls_cipher_get_tag_size(algo);
     807             : 
     808       14558 :         if (key_size != encryption_key->blob.length) {
     809           0 :                 return NT_STATUS_INTERNAL_ERROR;
     810             :         }
     811             : 
     812       14558 :         if (tag_size != 16) {
     813           0 :                 return NT_STATUS_INTERNAL_ERROR;
     814             :         }
     815             : 
     816       14558 :         key = (gnutls_datum_t) {
     817       14558 :                 .data = encryption_key->blob.data,
     818             :                 .size = key_size,
     819             :         };
     820             : 
     821       14558 :         iv = (gnutls_datum_t) {
     822       14558 :                 .data = tf + SMB2_TF_NONCE,
     823             :                 .size = iv_size,
     824             :         };
     825             : 
     826       14558 :         if (encryption_key->cipher_hnd == NULL) {
     827        7858 :                 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
     828             :                                         algo,
     829             :                                         &key);
     830        7858 :                 if (rc < 0) {
     831           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     832           0 :                         goto out;
     833             :                 }
     834             :         }
     835             : 
     836       14558 :         memset(tf + SMB2_TF_NONCE + iv_size,
     837             :                0,
     838       14558 :                16 - iv_size);
     839             : 
     840       14558 :         if (use_encryptv2) {
     841       14558 :                 uint8_t tag[tag_size];
     842         990 :                 giovec_t auth_iov[1];
     843             : 
     844       14558 :                 auth_iov[0] = (giovec_t) {
     845       13568 :                         .iov_base = tf + SMB2_TF_NONCE,
     846             :                         .iov_len  = a_total,
     847             :                 };
     848             : 
     849       14558 :                 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
     850       13568 :                                                   iv.data,
     851       13568 :                                                   iv.size,
     852             :                                                   auth_iov,
     853             :                                                   1,
     854       13568 :                                                   &vector[1],
     855             :                                                   count - 1,
     856             :                                                   tag,
     857             :                                                   &tag_size);
     858       14558 :                 if (rc < 0) {
     859           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     860           0 :                         goto out;
     861             :                 }
     862             : 
     863       14558 :                 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
     864             :         } else
     865             :         {
     866           0 :                 size_t ptext_size = m_total;
     867           0 :                 uint8_t *ptext = NULL;
     868           0 :                 size_t ctext_size = m_total + tag_size;
     869           0 :                 uint8_t *ctext = NULL;
     870           0 :                 size_t len = 0;
     871             :                 int i;
     872           0 :                 TALLOC_CTX *tmp_ctx = NULL;
     873             : 
     874             :                 /*
     875             :                  * If we come from python bindings, we don't have a stackframe
     876             :                  * around, so use the NULL context.
     877             :                  *
     878             :                  * This is fine as we make sure we free the memory.
     879             :                  */
     880           0 :                 if (talloc_stackframe_exists()) {
     881           0 :                         tmp_ctx = talloc_tos();
     882             :                 }
     883             : 
     884           0 :                 ptext = talloc_size(tmp_ctx, ptext_size);
     885           0 :                 if (ptext == NULL) {
     886           0 :                         status = NT_STATUS_NO_MEMORY;
     887           0 :                         goto out;
     888             :                 }
     889             : 
     890           0 :                 ctext = talloc_size(tmp_ctx, ctext_size);
     891           0 :                 if (ctext == NULL) {
     892           0 :                         TALLOC_FREE(ptext);
     893           0 :                         status = NT_STATUS_NO_MEMORY;
     894           0 :                         goto out;
     895             :                 }
     896             : 
     897           0 :                 for (i = 1; i < count; i++) {
     898           0 :                         if (vector[i].iov_base != NULL) {
     899           0 :                                 memcpy(ptext + len,
     900           0 :                                        vector[i].iov_base,
     901           0 :                                        vector[i].iov_len);
     902             :                         }
     903             : 
     904           0 :                         len += vector[i].iov_len;
     905           0 :                         if (len > ptext_size) {
     906           0 :                                 TALLOC_FREE(ptext);
     907           0 :                                 TALLOC_FREE(ctext);
     908           0 :                                 status = NT_STATUS_INTERNAL_ERROR;
     909           0 :                                 goto out;
     910             :                         }
     911             :                 }
     912             : 
     913           0 :                 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
     914           0 :                                                 iv.data,
     915           0 :                                                 iv.size,
     916           0 :                                                 tf + SMB2_TF_NONCE,
     917             :                                                 a_total,
     918             :                                                 tag_size,
     919             :                                                 ptext,
     920             :                                                 ptext_size,
     921             :                                                 ctext,
     922             :                                                 &ctext_size);
     923           0 :                 if (rc < 0 || ctext_size != m_total + tag_size) {
     924           0 :                         TALLOC_FREE(ptext);
     925           0 :                         TALLOC_FREE(ctext);
     926           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     927           0 :                         goto out;
     928             :                 }
     929             : 
     930           0 :                 len = 0;
     931           0 :                 for (i = 1; i < count; i++) {
     932           0 :                         if (vector[i].iov_base != NULL) {
     933           0 :                                 memcpy(vector[i].iov_base,
     934           0 :                                        ctext + len,
     935           0 :                                        vector[i].iov_len);
     936             :                         }
     937             : 
     938           0 :                         len += vector[i].iov_len;
     939             :                 }
     940             : 
     941           0 :                 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
     942             : 
     943           0 :                 TALLOC_FREE(ptext);
     944           0 :                 TALLOC_FREE(ctext);
     945             :         }
     946             : 
     947       14558 :         DBG_INFO("Encrypted SMB2 message\n");
     948             : 
     949       13568 :         status = NT_STATUS_OK;
     950       14558 : out:
     951       14558 :         return status;
     952             : }
     953             : 
     954       14543 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
     955             :                                   struct iovec *vector,
     956             :                                   int count)
     957             : {
     958       14543 :         bool use_encryptv2 = false;
     959         990 :         uint16_t cipher_id;
     960         990 :         uint8_t *tf;
     961         990 :         uint16_t flags;
     962         990 :         size_t a_total;
     963         990 :         ssize_t m_total;
     964       14543 :         uint32_t msg_size = 0;
     965       14543 :         uint32_t iv_size = 0;
     966       14543 :         uint32_t key_size = 0;
     967       14543 :         size_t tag_size = 0;
     968       14543 :         gnutls_cipher_algorithm_t algo = 0;
     969         990 :         gnutls_datum_t key;
     970         990 :         gnutls_datum_t iv;
     971         990 :         NTSTATUS status;
     972         990 :         int rc;
     973             : 
     974       14543 :         if (count < 1) {
     975           0 :                 return NT_STATUS_INVALID_PARAMETER;
     976             :         }
     977             : 
     978       14543 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
     979           0 :                 return NT_STATUS_INVALID_PARAMETER;
     980             :         }
     981             : 
     982       14543 :         tf = (uint8_t *)vector[0].iov_base;
     983             : 
     984       14543 :         if (!smb2_signing_key_valid(decryption_key)) {
     985           0 :                 DBG_WARNING("No decryption key for SMB2 signing\n");
     986           0 :                 return NT_STATUS_ACCESS_DENIED;
     987             :         }
     988       14543 :         cipher_id = decryption_key->cipher_algo_id;
     989             : 
     990       14543 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
     991             : 
     992       14543 :         m_total = iov_buflen(&vector[1], count-1);
     993       14543 :         if (m_total == -1) {
     994           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     995             :         }
     996             : 
     997       14543 :         flags = SVAL(tf, SMB2_TF_FLAGS);
     998       14543 :         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
     999             : 
    1000       14543 :         if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
    1001           0 :                 return NT_STATUS_ACCESS_DENIED;
    1002             :         }
    1003             : 
    1004       14543 :         if (msg_size != m_total) {
    1005           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1006             :         }
    1007             : 
    1008       14543 :         switch (cipher_id) {
    1009        1116 :         case SMB2_ENCRYPTION_AES128_CCM:
    1010        1116 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
    1011        1116 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
    1012             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
    1013        1116 :                 use_encryptv2 = true;
    1014             : #endif
    1015        1116 :                 break;
    1016       12783 :         case SMB2_ENCRYPTION_AES128_GCM:
    1017       12783 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
    1018       12783 :                 iv_size = gnutls_cipher_get_iv_size(algo);
    1019       12783 :                 use_encryptv2 = true;
    1020       12783 :                 break;
    1021         216 :         case SMB2_ENCRYPTION_AES256_CCM:
    1022         216 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
    1023         216 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
    1024             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
    1025         216 :                 use_encryptv2 = true;
    1026             : #endif
    1027         216 :                 break;
    1028         216 :         case SMB2_ENCRYPTION_AES256_GCM:
    1029         216 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
    1030         216 :                 iv_size = gnutls_cipher_get_iv_size(algo);
    1031         216 :                 use_encryptv2 = true;
    1032         216 :                 break;
    1033           0 :         default:
    1034           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1035             :         }
    1036             : 
    1037       14543 :         key_size = gnutls_cipher_get_key_size(algo);
    1038       14543 :         tag_size = gnutls_cipher_get_tag_size(algo);
    1039             : 
    1040       14543 :         if (key_size != decryption_key->blob.length) {
    1041           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1042             :         }
    1043             : 
    1044       14543 :         if (tag_size != 16) {
    1045           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1046             :         }
    1047             : 
    1048       14543 :         key = (gnutls_datum_t) {
    1049       14543 :                 .data = decryption_key->blob.data,
    1050             :                 .size = key_size,
    1051             :         };
    1052             : 
    1053       14543 :         iv = (gnutls_datum_t) {
    1054       14543 :                 .data = tf + SMB2_TF_NONCE,
    1055             :                 .size = iv_size,
    1056             :         };
    1057             : 
    1058       14543 :         if (decryption_key->cipher_hnd == NULL) {
    1059        1333 :                 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
    1060             :                                              algo,
    1061             :                                              &key);
    1062        1333 :                 if (rc < 0) {
    1063           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1064           0 :                         goto out;
    1065             :                 }
    1066             :         }
    1067             : 
    1068       14543 :         if (use_encryptv2) {
    1069         990 :                 giovec_t auth_iov[1];
    1070             : 
    1071       14543 :                 auth_iov[0] = (giovec_t) {
    1072       13553 :                         .iov_base = tf + SMB2_TF_NONCE,
    1073             :                         .iov_len  = a_total,
    1074             :                 };
    1075             : 
    1076       15533 :                 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
    1077       13553 :                                                   iv.data,
    1078       13553 :                                                   iv.size,
    1079             :                                                   auth_iov,
    1080             :                                                   1,
    1081       13553 :                                                   &vector[1],
    1082             :                                                   count - 1,
    1083       14543 :                                                   tf + SMB2_TF_SIGNATURE,
    1084             :                                                   tag_size);
    1085       14543 :                 if (rc < 0) {
    1086           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1087           0 :                         goto out;
    1088             :                 }
    1089             :         } else
    1090             :         {
    1091           0 :                 size_t ctext_size = m_total + tag_size;
    1092           0 :                 uint8_t *ctext = NULL;
    1093           0 :                 size_t ptext_size = m_total;
    1094           0 :                 uint8_t *ptext = NULL;
    1095           0 :                 size_t len = 0;
    1096             :                 int i;
    1097           0 :                 TALLOC_CTX *tmp_ctx = NULL;
    1098             : 
    1099             :                 /*
    1100             :                  * If we come from python bindings, we don't have a stackframe
    1101             :                  * around, so use the NULL context.
    1102             :                  *
    1103             :                  * This is fine as we make sure we free the memory.
    1104             :                  */
    1105           0 :                 if (talloc_stackframe_exists()) {
    1106           0 :                         tmp_ctx = talloc_tos();
    1107             :                 }
    1108             : 
    1109             :                 /* GnuTLS doesn't have a iovec API for decryption yet */
    1110             : 
    1111           0 :                 ptext = talloc_size(tmp_ctx, ptext_size);
    1112           0 :                 if (ptext == NULL) {
    1113           0 :                         status = NT_STATUS_NO_MEMORY;
    1114           0 :                         goto out;
    1115             :                 }
    1116             : 
    1117           0 :                 ctext = talloc_size(tmp_ctx, ctext_size);
    1118           0 :                 if (ctext == NULL) {
    1119           0 :                         TALLOC_FREE(ptext);
    1120           0 :                         status = NT_STATUS_NO_MEMORY;
    1121           0 :                         goto out;
    1122             :                 }
    1123             : 
    1124             : 
    1125           0 :                 for (i = 1; i < count; i++) {
    1126           0 :                         memcpy(ctext + len,
    1127           0 :                                vector[i].iov_base,
    1128           0 :                                vector[i].iov_len);
    1129             : 
    1130           0 :                         len += vector[i].iov_len;
    1131             :                 }
    1132           0 :                 if (len != m_total) {
    1133           0 :                         TALLOC_FREE(ptext);
    1134           0 :                         TALLOC_FREE(ctext);
    1135           0 :                         status = NT_STATUS_INTERNAL_ERROR;
    1136           0 :                         goto out;
    1137             :                 }
    1138             : 
    1139           0 :                 memcpy(ctext + len,
    1140           0 :                        tf + SMB2_TF_SIGNATURE,
    1141             :                        tag_size);
    1142             : 
    1143             :                 /* This function will verify the tag */
    1144           0 :                 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
    1145           0 :                                                 iv.data,
    1146           0 :                                                 iv.size,
    1147           0 :                                                 tf + SMB2_TF_NONCE,
    1148             :                                                 a_total,
    1149             :                                                 tag_size,
    1150             :                                                 ctext,
    1151             :                                                 ctext_size,
    1152             :                                                 ptext,
    1153             :                                                 &ptext_size);
    1154           0 :                 if (rc < 0) {
    1155           0 :                         TALLOC_FREE(ptext);
    1156           0 :                         TALLOC_FREE(ctext);
    1157           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1158           0 :                         goto out;
    1159             :                 }
    1160           0 :                 if (ptext_size != m_total) {
    1161           0 :                         TALLOC_FREE(ptext);
    1162           0 :                         TALLOC_FREE(ctext);
    1163           0 :                         rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
    1164           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1165           0 :                         goto out;
    1166             :                 }
    1167             : 
    1168           0 :                 len = 0;
    1169           0 :                 for (i = 1; i < count; i++) {
    1170           0 :                         memcpy(vector[i].iov_base,
    1171           0 :                                ptext + len,
    1172           0 :                                vector[i].iov_len);
    1173             : 
    1174           0 :                         len += vector[i].iov_len;
    1175             :                 }
    1176             : 
    1177           0 :                 TALLOC_FREE(ptext);
    1178           0 :                 TALLOC_FREE(ctext);
    1179             :         }
    1180             : 
    1181       14543 :         DBG_INFO("Decrypted SMB2 message\n");
    1182             : 
    1183       13553 :         status = NT_STATUS_OK;
    1184       14543 : out:
    1185       14543 :         return status;
    1186             : }

Generated by: LCOV version 1.14