LCOV - code coverage report
Current view: top level - libcli/smb - smb2_signing.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 502 628 79.9 %
Date: 2021-09-23 10:06:22 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             : #ifndef HAVE_GNUTLS_AES_CMAC
      31             : #include "lib/crypto/aes.h"
      32             : #include "lib/crypto/aes_cmac_128.h"
      33             : #endif
      34             : 
      35             : #include "lib/crypto/gnutls_helpers.h"
      36             : 
      37       42490 : void smb2_signing_derivations_fill_const_stack(struct smb2_signing_derivations *ds,
      38             :                                                enum protocol_types protocol,
      39             :                                                const DATA_BLOB preauth_hash)
      40             : {
      41       42490 :         *ds = (struct smb2_signing_derivations) { .signing = NULL, };
      42             : 
      43       42490 :         if (protocol >= PROTOCOL_SMB3_11) {
      44       36246 :                 struct smb2_signing_derivation *d = NULL;
      45             : 
      46       36246 :                 SMB_ASSERT(preauth_hash.length != 0);
      47             : 
      48       36246 :                 d = &ds->__signing;
      49       36246 :                 ds->signing = d;
      50       36246 :                 d->label = data_blob_string_const_null("SMBSigningKey");
      51       36246 :                 d->context = preauth_hash;
      52             : 
      53       36246 :                 d = &ds->__cipher_c2s;
      54       36246 :                 ds->cipher_c2s = d;
      55       36246 :                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
      56       36246 :                 d->context = preauth_hash;
      57             : 
      58       36246 :                 d = &ds->__cipher_s2c;
      59       36246 :                 ds->cipher_s2c = d;
      60       36246 :                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
      61       36246 :                 d->context = preauth_hash;
      62             : 
      63       36246 :                 d = &ds->__application;
      64       36246 :                 ds->application = d;
      65       36246 :                 d->label = data_blob_string_const_null("SMBAppKey");
      66       36246 :                 d->context = preauth_hash;
      67             : 
      68        6244 :         } else if (protocol >= PROTOCOL_SMB3_00) {
      69         112 :                 struct smb2_signing_derivation *d = NULL;
      70             : 
      71         112 :                 d = &ds->__signing;
      72         112 :                 ds->signing = d;
      73         112 :                 d->label = data_blob_string_const_null("SMB2AESCMAC");
      74         112 :                 d->context = data_blob_string_const_null("SmbSign");
      75             : 
      76         112 :                 d = &ds->__cipher_c2s;
      77         112 :                 ds->cipher_c2s = d;
      78         112 :                 d->label = data_blob_string_const_null("SMB2AESCCM");
      79         112 :                 d->context = data_blob_string_const_null("ServerIn ");
      80             : 
      81         112 :                 d = &ds->__cipher_s2c;
      82         112 :                 ds->cipher_s2c = d;
      83         112 :                 d->label = data_blob_string_const_null("SMB2AESCCM");
      84         112 :                 d->context = data_blob_string_const_null("ServerOut");
      85             : 
      86         112 :                 d = &ds->__application;
      87         112 :                 ds->application = d;
      88         112 :                 d->label = data_blob_string_const_null("SMB2APP");
      89         112 :                 d->context = data_blob_string_const_null("SmbRpc");
      90             :         }
      91       42490 : }
      92             : 
      93      278619 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
      94             : {
      95      278619 :         if (key->hmac_hnd != NULL) {
      96        6766 :                 gnutls_hmac_deinit(key->hmac_hnd, NULL);
      97        6766 :                 key->hmac_hnd = NULL;
      98             :         }
      99             : 
     100      278619 :         if (key->cipher_hnd != NULL) {
     101       40747 :                 gnutls_aead_cipher_deinit(key->cipher_hnd);
     102       40747 :                 key->cipher_hnd = NULL;
     103             :         }
     104             : 
     105      278619 :         return 0;
     106             : }
     107             : 
     108       46794 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
     109             :                                const struct smb2_signing_key *src,
     110             :                                struct smb2_signing_key **_dst)
     111             : {
     112       46794 :         struct smb2_signing_key *dst = NULL;
     113             : 
     114       46794 :         dst = talloc_zero(mem_ctx, struct smb2_signing_key);
     115       46794 :         if (dst == NULL) {
     116           0 :                 return NT_STATUS_NO_MEMORY;
     117             :         }
     118       46794 :         talloc_set_destructor(dst, smb2_signing_key_destructor);
     119             : 
     120       46794 :         dst->sign_algo_id = src->sign_algo_id;
     121       46794 :         dst->cipher_algo_id = src->cipher_algo_id;
     122             : 
     123       46794 :         if (src->blob.length == 0) {
     124           0 :                 *_dst = dst;
     125           0 :                 return NT_STATUS_OK;
     126             :         }
     127             : 
     128       46794 :         dst->blob = data_blob_talloc_zero(dst, src->blob.length);
     129       46794 :         if (dst->blob.length == 0) {
     130           0 :                 TALLOC_FREE(dst);
     131           0 :                 return NT_STATUS_NO_MEMORY;
     132             :         }
     133       46794 :         talloc_keep_secret(dst->blob.data);
     134       47572 :         memcpy(dst->blob.data, src->blob.data, dst->blob.length);
     135             : 
     136       46794 :         *_dst = dst;
     137       46794 :         return NT_STATUS_OK;
     138             : }
     139             : 
     140      257725 : static NTSTATUS smb2_signing_key_create(TALLOC_CTX *mem_ctx,
     141             :                                         uint16_t sign_algo_id,
     142             :                                         uint16_t cipher_algo_id,
     143             :                                         const DATA_BLOB *master_key,
     144             :                                         const struct smb2_signing_derivation *d,
     145             :                                         struct smb2_signing_key **_key)
     146             : {
     147      257725 :         struct smb2_signing_key *key = NULL;
     148      257725 :         size_t in_key_length = 16;
     149      257725 :         size_t out_key_length = 16;
     150             :         NTSTATUS status;
     151             : 
     152      257725 :         if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
     153      179643 :                 SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
     154             :         }
     155      257725 :         if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
     156       78082 :                 SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
     157             :         }
     158             : 
     159      257725 :         key = talloc_zero(mem_ctx, struct smb2_signing_key);
     160      257725 :         if (key == NULL) {
     161           0 :                 return NT_STATUS_NO_MEMORY;
     162             :         }
     163      257725 :         talloc_set_destructor(key, smb2_signing_key_destructor);
     164             : 
     165      257725 :         key->sign_algo_id = sign_algo_id;
     166      257725 :         key->cipher_algo_id = cipher_algo_id;
     167             : 
     168      257725 :         if (master_key == NULL) {
     169       91456 :                 SMB_ASSERT(d == NULL);
     170             : 
     171       91456 :                 *_key = key;
     172       91456 :                 return NT_STATUS_OK;
     173             :         }
     174             : 
     175             :         /*
     176             :          * Per default use the full key.
     177             :          */
     178      166269 :         in_key_length = out_key_length = master_key->length;
     179      166269 :         switch (sign_algo_id) {
     180       75680 :         case SMB2_SIGNING_INVALID_ALGO:
     181             :                 /*
     182             :                  * This means we're processing cipher_algo_id below
     183             :                  */
     184       75680 :                 break;
     185        4815 :         case SMB2_SIGNING_MD5_SMB1:
     186        4815 :                 SMB_ASSERT(d == NULL);
     187        4683 :                 break;
     188       84222 :         case SMB2_SIGNING_HMAC_SHA256:
     189             :         case SMB2_SIGNING_AES128_CMAC:
     190             :         case SMB2_SIGNING_AES128_GMAC:
     191             :                 /*
     192             :                  * signing keys are padded or truncated to
     193             :                  * 16 bytes.
     194             :                  *
     195             :                  * Even with master_key->length = 0,
     196             :                  * we need to use 16 zeros.
     197             :                  */
     198       84222 :                 in_key_length = out_key_length = 16;
     199       84222 :                 break;
     200           0 :         default:
     201           0 :                 DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id);
     202           0 :                 return NT_STATUS_HMAC_NOT_SUPPORTED;
     203             :         }
     204      166269 :         switch (cipher_algo_id) {
     205       87349 :         case SMB2_ENCRYPTION_INVALID_ALGO:
     206             :                 /*
     207             :                  * This means we're processing sign_algo_id above
     208             :                  */
     209       87349 :                 break;
     210        8080 :         case SMB2_ENCRYPTION_NONE:
     211             :                 /*
     212             :                  * No encryption negotiated.
     213             :                  */
     214        8080 :                 break;
     215       69072 :         case SMB2_ENCRYPTION_AES128_CCM:
     216             :         case SMB2_ENCRYPTION_AES128_GCM:
     217             :                 /*
     218             :                  * encryption keys are padded or truncated to
     219             :                  * 16 bytes.
     220             :                  */
     221       69072 :                 if (master_key->length == 0) {
     222           0 :                         DBG_ERR("cipher_algo_id[%u] without key\n",
     223             :                                 cipher_algo_id);
     224           0 :                         return NT_STATUS_NO_USER_SESSION_KEY;
     225             :                 }
     226       67520 :                 in_key_length = out_key_length = 16;
     227       67520 :                 break;
     228          80 :         case SMB2_ENCRYPTION_AES256_CCM:
     229             :         case SMB2_ENCRYPTION_AES256_GCM:
     230             :                 /*
     231             :                  * AES256 uses the available input and
     232             :                  * generated a 32 byte encryption key.
     233             :                  */
     234          80 :                 if (master_key->length == 0) {
     235           0 :                         DBG_ERR("cipher_algo_id[%u] without key\n",
     236             :                                 cipher_algo_id);
     237           0 :                         return NT_STATUS_NO_USER_SESSION_KEY;
     238             :                 }
     239          80 :                 out_key_length = 32;
     240          80 :                 break;
     241           0 :         default:
     242           0 :                 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id);
     243           0 :                 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG;
     244             :         }
     245             : 
     246      164717 :         if (out_key_length == 0) {
     247           0 :                 *_key = key;
     248           0 :                 return NT_STATUS_OK;
     249             :         }
     250             : 
     251      166269 :         key->blob = data_blob_talloc_zero(key, out_key_length);
     252      166269 :         if (key->blob.length == 0) {
     253           0 :                 TALLOC_FREE(key);
     254           0 :                 return NT_STATUS_NO_MEMORY;
     255             :         }
     256      166269 :         talloc_keep_secret(key->blob.data);
     257      169509 :         memcpy(key->blob.data,
     258      166269 :                master_key->data,
     259      166269 :                MIN(key->blob.length, master_key->length));
     260             : 
     261      166269 :         if (d == NULL) {
     262       24769 :                 *_key = key;
     263       24769 :                 return NT_STATUS_OK;
     264             :         }
     265             : 
     266      392152 :         status = smb2_key_derivation(key->blob.data, in_key_length,
     267      141500 :                                      d->label.data, d->label.length,
     268      141500 :                                      d->context.data, d->context.length,
     269             :                                      key->blob.data, out_key_length);
     270      141500 :         if (!NT_STATUS_IS_OK(status)) {
     271           0 :                 TALLOC_FREE(key);
     272           0 :                 return status;
     273             :         }
     274             : 
     275      141500 :         *_key = key;
     276      141500 :         return NT_STATUS_OK;
     277             : }
     278             : 
     279      179643 : NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
     280             :                                       uint16_t sign_algo_id,
     281             :                                       const DATA_BLOB *master_key,
     282             :                                       const struct smb2_signing_derivation *d,
     283             :                                       struct smb2_signing_key **_key)
     284             : {
     285      179643 :         return smb2_signing_key_create(mem_ctx,
     286             :                                        sign_algo_id,
     287             :                                        SMB2_ENCRYPTION_INVALID_ALGO,
     288             :                                        master_key,
     289             :                                        d,
     290             :                                        _key);
     291             : }
     292             : 
     293       78082 : NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
     294             :                                         uint16_t cipher_algo_id,
     295             :                                         const DATA_BLOB *master_key,
     296             :                                         const struct smb2_signing_derivation *d,
     297             :                                         struct smb2_signing_key **_key)
     298             : {
     299       78082 :         return smb2_signing_key_create(mem_ctx,
     300             :                                        SMB2_SIGNING_INVALID_ALGO,
     301             :                                        cipher_algo_id,
     302             :                                        master_key,
     303             :                                        d,
     304             :                                        _key);
     305             : }
     306             : 
     307     9591459 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
     308             : {
     309     9591459 :         if (key == NULL) {
     310      776095 :                 return false;
     311             :         }
     312             : 
     313     8814178 :         if (key->blob.length == 0 || key->blob.data == NULL) {
     314      244246 :                 return false;
     315             :         }
     316             : 
     317     8567198 :         return true;
     318             : }
     319             : 
     320     2306547 : static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd,
     321             :                                   const uint8_t *iv, size_t iv_size,
     322             :                                   const giovec_t *auth_iov, uint8_t auth_iovcnt,
     323             :                                   uint8_t *tag, size_t _tag_size)
     324             : {
     325     2306547 :         size_t tag_size = _tag_size;
     326             :         int rc;
     327             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
     328             : 
     329      692105 :         rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
     330             :                                           iv, iv_size,
     331             :                                           auth_iov, auth_iovcnt,
     332             :                                           NULL, 0,
     333             :                                           tag, &tag_size);
     334      692105 :         if (rc < 0) {
     335           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     336             :         }
     337             : 
     338      692105 :         return NT_STATUS_OK;
     339             : #else /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
     340     1614442 :         TALLOC_CTX *tmp_ctx = NULL;
     341     1614442 :         size_t atext_size = 0;
     342     1614442 :         uint8_t *atext = NULL;
     343     1614442 :         size_t len = 0;
     344             :         size_t i;
     345             : 
     346             :         /*
     347             :          * If we come from python bindings, we don't have a stackframe
     348             :          * around, so use the NULL context.
     349             :          *
     350             :          * This is fine as we make sure we free the memory.
     351             :          */
     352     1614442 :         if (talloc_stackframe_exists()) {
     353     1614224 :                 tmp_ctx = talloc_tos();
     354             :         }
     355             : 
     356     8058344 :         for (i=0; i < auth_iovcnt; i++) {
     357     6443902 :                 atext_size += auth_iov[i].iov_len;
     358             :         }
     359             : 
     360     1614442 :         atext = talloc_size(tmp_ctx, atext_size);
     361     1614442 :         if (atext == NULL) {
     362           0 :                 return NT_STATUS_NO_MEMORY;
     363             :         }
     364             : 
     365     8025166 :         for (i = 0; i < auth_iovcnt; i++) {
     366    13019994 :                 memcpy(atext + len,
     367     6443902 :                        auth_iov[i].iov_base,
     368     6443902 :                        auth_iov[i].iov_len);
     369             : 
     370     6443902 :                 len += auth_iov[i].iov_len;
     371     6443902 :                 if (len > atext_size) {
     372           0 :                         TALLOC_FREE(atext);
     373           0 :                         return NT_STATUS_INTERNAL_ERROR;
     374             :                 }
     375             :         }
     376             : 
     377     1614442 :         rc = gnutls_aead_cipher_encrypt(cipher_hnd,
     378             :                                         iv, iv_size,
     379             :                                         atext,
     380             :                                         atext_size,
     381             :                                         tag_size,
     382             :                                         NULL, 0,
     383             :                                         tag, &tag_size);
     384     1614442 :         TALLOC_FREE(atext);
     385     1614442 :         if (rc < 0) {
     386           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     387             :         }
     388             : 
     389     1614442 :         return NT_STATUS_OK;
     390             : #endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
     391             : }
     392             : 
     393     3377909 : static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
     394             :                                             uint16_t sign_algo_id,
     395             :                                             const struct iovec *vector,
     396             :                                             int count,
     397             :                                             uint8_t signature[16])
     398             : {
     399     3377909 :         const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
     400             :         uint16_t opcode;
     401             :         uint32_t flags;
     402             :         uint64_t msg_id;
     403             :         static const uint8_t zero_sig[16] = { 0, };
     404     3377909 :         gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
     405             :         int i;
     406             : 
     407             :         /*
     408             :          * We expect
     409             :          * - SMB2 HDR
     410             :          * - SMB2 BODY FIXED
     411             :          * - (optional) SMB2 BODY DYN
     412             :          * - (optional) PADDING
     413             :          */
     414     3377909 :         SMB_ASSERT(count >= 2);
     415     3377909 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     416     3377909 :         SMB_ASSERT(count <= 4);
     417             : 
     418     3377909 :         opcode = SVAL(hdr, SMB2_HDR_OPCODE);
     419     3377909 :         flags = IVAL(hdr, SMB2_HDR_FLAGS);
     420     3377909 :         if (flags & SMB2_HDR_FLAG_REDIRECT) {
     421     1705704 :                 NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
     422     1705704 :                 if (NT_STATUS_EQUAL(pdu_status, NT_STATUS_PENDING)) {
     423           0 :                         DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode);
     424           0 :                         return NT_STATUS_INTERNAL_ERROR;
     425             :                 }
     426     1705704 :                 if (opcode == SMB2_OP_CANCEL) {
     427           0 :                         DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
     428           0 :                         return NT_STATUS_INTERNAL_ERROR;
     429             :                 }
     430             :         }
     431     3377909 :         msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
     432     3377909 :         if (msg_id == 0) {
     433           0 :                 DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
     434           0 :                 return NT_STATUS_INTERNAL_ERROR;
     435             :         }
     436     3377909 :         if (msg_id == UINT64_MAX) {
     437           0 :                 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
     438           0 :                 return NT_STATUS_INTERNAL_ERROR;
     439             :         }
     440             : 
     441     3377909 :         switch (sign_algo_id) {
     442     2306547 :         case SMB2_SIGNING_AES128_GMAC: {
     443     2306547 :                 gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
     444     2306547 :                 uint32_t key_size = gnutls_cipher_get_key_size(algo);
     445     2306547 :                 uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
     446     2306547 :                 size_t tag_size = gnutls_cipher_get_tag_size(algo);
     447     3920989 :                 gnutls_datum_t key = {
     448     2306547 :                         .data = signing_key->blob.data,
     449     2306547 :                         .size = MIN(signing_key->blob.length, key_size),
     450             :                 };
     451     2306547 :                 uint64_t high_bits = 0;
     452     2306547 :                 uint8_t iv[AES_BLOCK_SIZE] = {0};
     453     2306547 :                 giovec_t auth_iov[count+1];
     454     2306547 :                 size_t auth_iovcnt = 0;
     455             :                 NTSTATUS status;
     456             :                 int rc;
     457             : 
     458     2306547 :                 high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
     459     2306547 :                 if (opcode == SMB2_OP_CANCEL) {
     460          32 :                         high_bits |= SMB2_HDR_FLAG_ASYNC;
     461             :                 }
     462     2306547 :                 SBVAL(iv, 0, msg_id);
     463     2306547 :                 SBVAL(iv, 8, high_bits);
     464             : 
     465     2306547 :                 if (signing_key->cipher_hnd == NULL) {
     466       36982 :                         rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
     467             :                                                      algo,
     468             :                                                      &key);
     469       36982 :                         if (rc < 0) {
     470           0 :                                 return gnutls_error_to_ntstatus(rc,
     471             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     472             :                         }
     473             :                 }
     474             : 
     475     2306547 :                 SMB_ASSERT(key_size == 16);
     476     2306547 :                 SMB_ASSERT(iv_size == 12);
     477     2306547 :                 SMB_ASSERT(tag_size == 16);
     478             : 
     479     2306547 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     480             :                         .iov_base = discard_const_p(uint8_t, hdr),
     481             :                         .iov_len  = SMB2_HDR_SIGNATURE,
     482             :                 };
     483     2306547 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     484             :                         .iov_base = discard_const_p(uint8_t, zero_sig),
     485             :                         .iov_len  = 16,
     486             :                 };
     487     6902080 :                 for (i=1; i < count; i++) {
     488     7810551 :                         auth_iov[auth_iovcnt++] = (giovec_t) {
     489     4595533 :                                 .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
     490     4595533 :                                 .iov_len  = vector[i].iov_len,
     491             :                         };
     492             :                 }
     493             : 
     494     2306547 :                 status = smb2_signing_gmac(signing_key->cipher_hnd,
     495             :                                            iv,
     496             :                                            iv_size,
     497             :                                            auth_iov,
     498             :                                            auth_iovcnt,
     499             :                                            signature,
     500             :                                            tag_size);
     501     2306547 :                 if (!NT_STATUS_IS_OK(status)) {
     502           0 :                         return status;
     503             :                 }
     504             : 
     505     2306547 :                 return NT_STATUS_OK;
     506             :         }       break;
     507             : 
     508        2466 :         case SMB2_SIGNING_AES128_CMAC:
     509             : #ifdef HAVE_GNUTLS_AES_CMAC
     510         831 :                 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
     511         831 :                 break;
     512             : #else /* NOT HAVE_GNUTLS_AES_CMAC */
     513             :         {
     514             :                 struct aes_cmac_128_context ctx;
     515        1635 :                 uint8_t key[AES_BLOCK_SIZE] = {0};
     516             : 
     517        3270 :                 memcpy(key,
     518        1635 :                        signing_key->blob.data,
     519        1635 :                        MIN(signing_key->blob.length, 16));
     520             : 
     521        1635 :                 aes_cmac_128_init(&ctx, key);
     522        1635 :                 aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
     523        1635 :                 aes_cmac_128_update(&ctx, zero_sig, 16);
     524        4900 :                 for (i=1; i < count; i++) {
     525        6530 :                         aes_cmac_128_update(&ctx,
     526        3265 :                                         (const uint8_t *)vector[i].iov_base,
     527        3265 :                                         vector[i].iov_len);
     528             :                 }
     529        1635 :                 aes_cmac_128_final(&ctx, signature);
     530             : 
     531        1635 :                 ZERO_ARRAY(key);
     532             : 
     533        1635 :                 return NT_STATUS_OK;
     534             :         }       break;
     535             : #endif
     536     1068896 :         case SMB2_SIGNING_HMAC_SHA256:
     537     1068896 :                 hmac_algo = GNUTLS_MAC_SHA256;
     538     1068896 :                 break;
     539             : 
     540           0 :         default:
     541           0 :                 return NT_STATUS_HMAC_NOT_SUPPORTED;
     542             :         }
     543             : 
     544     1069727 :         if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
     545     1069727 :                 uint8_t digest[gnutls_hash_get_len(hmac_algo)];
     546     2024599 :                 gnutls_datum_t key = {
     547     1069727 :                         .data = signing_key->blob.data,
     548     1069727 :                         .size = MIN(signing_key->blob.length, 16),
     549             :                 };
     550             :                 int rc;
     551             : 
     552     1069727 :                 if (signing_key->hmac_hnd == NULL) {
     553       11368 :                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
     554             :                                               hmac_algo,
     555        6810 :                                               key.data,
     556        6810 :                                               key.size);
     557        6810 :                         if (rc < 0) {
     558           0 :                                 return gnutls_error_to_ntstatus(rc,
     559             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     560             :                         }
     561             :                 }
     562             : 
     563     1069727 :                 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
     564     1069727 :                 if (rc < 0) {
     565           0 :                         return gnutls_error_to_ntstatus(rc,
     566             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     567             :                 }
     568     1069727 :                 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
     569     1069727 :                 if (rc < 0) {
     570           0 :                         return gnutls_error_to_ntstatus(rc,
     571             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     572             :                 }
     573             : 
     574     3197706 :                 for (i = 1; i < count; i++) {
     575     4027844 :                         rc = gnutls_hmac(signing_key->hmac_hnd,
     576     2127979 :                                          vector[i].iov_base,
     577     2127979 :                                          vector[i].iov_len);
     578     2127979 :                         if (rc < 0) {
     579           0 :                                 return gnutls_error_to_ntstatus(rc,
     580             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     581             :                         }
     582             :                 }
     583     1069727 :                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
     584     1069727 :                 memcpy(signature, digest, 16);
     585     1069727 :                 ZERO_ARRAY(digest);
     586     1069727 :                 return NT_STATUS_OK;
     587             :         }
     588             : 
     589           0 :         return NT_STATUS_HMAC_NOT_SUPPORTED;
     590             : }
     591             : 
     592     1691904 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
     593             :                                struct iovec *vector,
     594             :                                int count)
     595             : {
     596             :         uint16_t sign_algo_id;
     597             :         uint8_t *hdr;
     598             :         uint64_t session_id;
     599             :         uint8_t res[16];
     600             :         NTSTATUS status;
     601             : 
     602             :         /*
     603             :          * We expect
     604             :          * - SMB2 HDR
     605             :          * - SMB2 BODY FIXED
     606             :          * - (optional) SMB2 BODY DYN
     607             :          * - (optional) PADDING
     608             :          */
     609     1691904 :         SMB_ASSERT(count >= 2);
     610     1691904 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     611     1691904 :         SMB_ASSERT(count <= 4);
     612             : 
     613     1691904 :         hdr = (uint8_t *)vector[0].iov_base;
     614             : 
     615     1691904 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     616     1691904 :         if (session_id == 0) {
     617             :                 /*
     618             :                  * do not sign messages with a zero session_id.
     619             :                  * See MS-SMB2 3.2.4.1.1
     620             :                  */
     621           0 :                 return NT_STATUS_OK;
     622             :         }
     623             : 
     624     1691904 :         if (!smb2_signing_key_valid(signing_key)) {
     625           0 :                 DBG_WARNING("No signing key for SMB2 signing\n");
     626           0 :                 return NT_STATUS_ACCESS_DENIED;
     627             :         }
     628             : 
     629     1708723 :         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
     630             : 
     631     1691904 :         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
     632             : 
     633     1691904 :         sign_algo_id = signing_key->sign_algo_id;
     634             : 
     635     1691904 :         status = smb2_signing_calc_signature(signing_key,
     636             :                                              sign_algo_id,
     637             :                                              vector,
     638             :                                              count,
     639             :                                              res);
     640     1691904 :         if (!NT_STATUS_IS_OK(status)) {
     641           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     642             :                         (unsigned)sign_algo_id, nt_errstr(status));
     643           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     644           0 :                         smb_panic(__location__);
     645             :                 }
     646           0 :                 return status;
     647             :         }
     648             : 
     649     1691904 :         DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
     650             :                  (unsigned)sign_algo_id));
     651             : 
     652     1708723 :         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
     653             : 
     654     1691904 :         return NT_STATUS_OK;
     655             : }
     656             : 
     657     1686005 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
     658             :                                 const struct iovec *vector,
     659             :                                 int count)
     660             : {
     661             :         uint16_t sign_algo_id;
     662             :         const uint8_t *hdr;
     663             :         const uint8_t *sig;
     664             :         uint64_t session_id;
     665             :         uint8_t res[16];
     666             :         NTSTATUS status;
     667             : 
     668             :         /*
     669             :          * We expect
     670             :          * - SMB2 HDR
     671             :          * - SMB2 BODY FIXED
     672             :          * - (optional) SMB2 BODY DYN
     673             :          * - (optional) PADDING
     674             :          */
     675     1686005 :         SMB_ASSERT(count >= 2);
     676     1686005 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     677     1686005 :         SMB_ASSERT(count <= 4);
     678             : 
     679     1686005 :         hdr = (const uint8_t *)vector[0].iov_base;
     680             : 
     681     1686005 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     682     1686005 :         if (session_id == 0) {
     683             :                 /*
     684             :                  * do not sign messages with a zero session_id.
     685             :                  * See MS-SMB2 3.2.4.1.1
     686             :                  */
     687           0 :                 return NT_STATUS_OK;
     688             :         }
     689             : 
     690     1686005 :         if (!smb2_signing_key_valid(signing_key)) {
     691             :                 /* we don't have the session key yet */
     692           0 :                 return NT_STATUS_OK;
     693             :         }
     694             : 
     695     1686005 :         sig = hdr+SMB2_HDR_SIGNATURE;
     696             : 
     697     1686005 :         sign_algo_id = signing_key->sign_algo_id;
     698             : 
     699     1686005 :         status = smb2_signing_calc_signature(signing_key,
     700             :                                              sign_algo_id,
     701             :                                              vector,
     702             :                                              count,
     703             :                                              res);
     704     1686005 :         if (!NT_STATUS_IS_OK(status)) {
     705           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     706             :                         (unsigned)sign_algo_id, nt_errstr(status));
     707           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     708           0 :                         status = NT_STATUS_ACCESS_DENIED;
     709             :                 }
     710           0 :                 return status;
     711             :         }
     712             : 
     713     1686005 :         if (memcmp_const_time(res, sig, 16) != 0) {
     714         202 :                 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
     715             :                          (unsigned)sign_algo_id));
     716         202 :                 dump_data(0, sig, 16);
     717         202 :                 dump_data(0, res, 16);
     718         202 :                 return NT_STATUS_ACCESS_DENIED;
     719             :         }
     720             : 
     721     1685803 :         return NT_STATUS_OK;
     722             : }
     723             : 
     724      142308 : NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
     725             :                              const uint8_t *Label, size_t Label_len,
     726             :                              const uint8_t *Context, size_t Context_len,
     727             :                              uint8_t *KO, size_t KO_len)
     728      142308 : {
     729      142308 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     730             :         uint8_t buf[4];
     731             :         static const uint8_t zero = 0;
     732      142308 :         const size_t digest_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
     733      142308 :         uint8_t digest[digest_len];
     734      142308 :         uint32_t i = 1;
     735      142308 :         uint32_t L = KO_len * 8;
     736             :         int rc;
     737             : 
     738      142308 :         if (KO_len > digest_len) {
     739           0 :                 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len, digest_len);
     740           0 :                 return NT_STATUS_INTERNAL_ERROR;
     741             :         }
     742             : 
     743      142308 :         switch (KO_len) {
     744      139200 :         case 16:
     745             :         case 32:
     746      139200 :                 break;
     747           0 :         default:
     748           0 :                 DBG_ERR("KO_len[%zu] not supported\n", KO_len);
     749           0 :                 return NT_STATUS_INTERNAL_ERROR;
     750             :         }
     751             : 
     752             :         /*
     753             :          * a simplified version of
     754             :          * "NIST Special Publication 800-108" section 5.1
     755             :          * using hmac-sha256.
     756             :          */
     757      142308 :         rc = gnutls_hmac_init(&hmac_hnd,
     758             :                               GNUTLS_MAC_SHA256,
     759             :                               KI,
     760             :                               KI_len);
     761      142308 :         if (rc < 0) {
     762           0 :                 return gnutls_error_to_ntstatus(rc,
     763             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     764             :         }
     765             : 
     766      142308 :         RSIVAL(buf, 0, i);
     767      142308 :         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
     768      142308 :         if (rc < 0) {
     769           0 :                 return gnutls_error_to_ntstatus(rc,
     770             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     771             :         }
     772      142308 :         rc = gnutls_hmac(hmac_hnd, Label, Label_len);
     773      142308 :         if (rc < 0) {
     774           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     775           0 :                 return gnutls_error_to_ntstatus(rc,
     776             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     777             :         }
     778      142308 :         rc = gnutls_hmac(hmac_hnd, &zero, 1);
     779      142308 :         if (rc < 0) {
     780           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     781           0 :                 return gnutls_error_to_ntstatus(rc,
     782             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     783             :         }
     784      142308 :         rc = gnutls_hmac(hmac_hnd, Context, Context_len);
     785      142308 :         if (rc < 0) {
     786           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     787           0 :                 return gnutls_error_to_ntstatus(rc,
     788             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     789             :         }
     790      142308 :         RSIVAL(buf, 0, L);
     791      142308 :         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
     792      142308 :         if (rc < 0) {
     793           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     794           0 :                 return gnutls_error_to_ntstatus(rc,
     795             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     796             :         }
     797             : 
     798      142308 :         gnutls_hmac_deinit(hmac_hnd, digest);
     799             : 
     800      145416 :         memcpy(KO, digest, KO_len);
     801             : 
     802      142308 :         ZERO_ARRAY(digest);
     803             : 
     804      142308 :         return NT_STATUS_OK;
     805             : }
     806             : 
     807       10095 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
     808             :                                   struct iovec *vector,
     809             :                                   int count)
     810             : {
     811             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
     812        1659 :         bool use_encryptv2 = false;
     813             : #endif
     814             :         uint16_t cipher_id;
     815             :         uint8_t *tf;
     816             :         size_t a_total;
     817             :         ssize_t m_total;
     818       10095 :         uint32_t iv_size = 0;
     819       10095 :         uint32_t key_size = 0;
     820       10095 :         size_t tag_size = 0;
     821       10095 :         gnutls_cipher_algorithm_t algo = 0;
     822             :         gnutls_datum_t key;
     823             :         gnutls_datum_t iv;
     824             :         NTSTATUS status;
     825             :         int rc;
     826             : 
     827       10095 :         if (count < 1) {
     828           0 :                 return NT_STATUS_INVALID_PARAMETER;
     829             :         }
     830             : 
     831       10095 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
     832           0 :                 return NT_STATUS_INVALID_PARAMETER;
     833             :         }
     834             : 
     835       10095 :         tf = (uint8_t *)vector[0].iov_base;
     836             : 
     837       10095 :         if (!smb2_signing_key_valid(encryption_key)) {
     838           0 :                 DBG_WARNING("No encryption key for SMB2 signing\n");
     839           0 :                 return NT_STATUS_ACCESS_DENIED;
     840             :         }
     841       10095 :         cipher_id = encryption_key->cipher_algo_id;
     842             : 
     843       10095 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
     844             : 
     845       10095 :         m_total = iov_buflen(&vector[1], count-1);
     846       10095 :         if (m_total == -1) {
     847           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     848             :         }
     849             : 
     850       10095 :         SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
     851       10095 :         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
     852             : 
     853       10095 :         switch (cipher_id) {
     854        1116 :         case SMB2_ENCRYPTION_AES128_CCM:
     855        1116 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
     856        1116 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     857             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     858         318 :                 use_encryptv2 = true;
     859             : #endif
     860        1116 :                 break;
     861        8619 :         case SMB2_ENCRYPTION_AES128_GCM:
     862        8619 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
     863        8619 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     864             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
     865        1233 :                 use_encryptv2 = true;
     866             : #endif
     867        8619 :                 break;
     868         180 :         case SMB2_ENCRYPTION_AES256_CCM:
     869         180 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
     870         180 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     871             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     872          54 :                 use_encryptv2 = true;
     873             : #endif
     874         180 :                 break;
     875         180 :         case SMB2_ENCRYPTION_AES256_GCM:
     876         180 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
     877         180 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     878             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
     879          54 :                 use_encryptv2 = true;
     880             : #endif
     881         180 :                 break;
     882           0 :         default:
     883           0 :                 return NT_STATUS_INVALID_PARAMETER;
     884             :         }
     885             : 
     886       10095 :         key_size = gnutls_cipher_get_key_size(algo);
     887       10095 :         tag_size = gnutls_cipher_get_tag_size(algo);
     888             : 
     889       10095 :         if (key_size != encryption_key->blob.length) {
     890           0 :                 return NT_STATUS_INTERNAL_ERROR;
     891             :         }
     892             : 
     893       10095 :         if (tag_size != 16) {
     894           0 :                 return NT_STATUS_INTERNAL_ERROR;
     895             :         }
     896             : 
     897       10095 :         key = (gnutls_datum_t) {
     898       10095 :                 .data = encryption_key->blob.data,
     899             :                 .size = key_size,
     900             :         };
     901             : 
     902       10095 :         iv = (gnutls_datum_t) {
     903       10095 :                 .data = tf + SMB2_TF_NONCE,
     904             :                 .size = iv_size,
     905             :         };
     906             : 
     907       10095 :         if (encryption_key->cipher_hnd == NULL) {
     908        5531 :                 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
     909             :                                         algo,
     910             :                                         &key);
     911        5531 :                 if (rc < 0) {
     912           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     913           0 :                         goto out;
     914             :                 }
     915             :         }
     916             : 
     917       10095 :         memset(tf + SMB2_TF_NONCE + iv_size,
     918             :                0,
     919       10095 :                16 - iv_size);
     920             : 
     921             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
     922        1659 :         if (use_encryptv2) {
     923        1659 :                 uint8_t tag[tag_size];
     924             :                 giovec_t auth_iov[1];
     925             : 
     926        1659 :                 auth_iov[0] = (giovec_t) {
     927        1659 :                         .iov_base = tf + SMB2_TF_NONCE,
     928             :                         .iov_len  = a_total,
     929             :                 };
     930             : 
     931        1659 :                 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
     932        1659 :                                                   iv.data,
     933        1659 :                                                   iv.size,
     934             :                                                   auth_iov,
     935             :                                                   1,
     936        1659 :                                                   &vector[1],
     937             :                                                   count - 1,
     938             :                                                   tag,
     939             :                                                   &tag_size);
     940        1659 :                 if (rc < 0) {
     941           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     942           0 :                         goto out;
     943             :                 }
     944             : 
     945        1659 :                 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
     946             :         } else
     947             : #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
     948             :         {
     949        8436 :                 size_t ptext_size = m_total;
     950        8436 :                 uint8_t *ptext = NULL;
     951        8436 :                 size_t ctext_size = m_total + tag_size;
     952        8436 :                 uint8_t *ctext = NULL;
     953        8436 :                 size_t len = 0;
     954             :                 int i;
     955        8436 :                 TALLOC_CTX *tmp_ctx = NULL;
     956             : 
     957             :                 /*
     958             :                  * If we come from python bindings, we don't have a stackframe
     959             :                  * around, so use the NULL context.
     960             :                  *
     961             :                  * This is fine as we make sure we free the memory.
     962             :                  */
     963        8436 :                 if (talloc_stackframe_exists()) {
     964        8424 :                         tmp_ctx = talloc_tos();
     965             :                 }
     966             : 
     967        8436 :                 ptext = talloc_size(tmp_ctx, ptext_size);
     968        8436 :                 if (ptext == NULL) {
     969           0 :                         status = NT_STATUS_NO_MEMORY;
     970           0 :                         goto out;
     971             :                 }
     972             : 
     973        8436 :                 ctext = talloc_size(tmp_ctx, ctext_size);
     974        8436 :                 if (ctext == NULL) {
     975           0 :                         TALLOC_FREE(ptext);
     976           0 :                         status = NT_STATUS_NO_MEMORY;
     977           0 :                         goto out;
     978             :                 }
     979             : 
     980       32932 :                 for (i = 1; i < count; i++) {
     981       24496 :                         if (vector[i].iov_base != NULL) {
     982       44048 :                                 memcpy(ptext + len,
     983       22024 :                                        vector[i].iov_base,
     984       22024 :                                        vector[i].iov_len);
     985             :                         }
     986             : 
     987       24496 :                         len += vector[i].iov_len;
     988       24496 :                         if (len > ptext_size) {
     989           0 :                                 TALLOC_FREE(ptext);
     990           0 :                                 TALLOC_FREE(ctext);
     991           0 :                                 status = NT_STATUS_INTERNAL_ERROR;
     992           0 :                                 goto out;
     993             :                         }
     994             :                 }
     995             : 
     996       16872 :                 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
     997        8436 :                                                 iv.data,
     998        8436 :                                                 iv.size,
     999        8436 :                                                 tf + SMB2_TF_NONCE,
    1000             :                                                 a_total,
    1001             :                                                 tag_size,
    1002             :                                                 ptext,
    1003             :                                                 ptext_size,
    1004             :                                                 ctext,
    1005             :                                                 &ctext_size);
    1006        8436 :                 if (rc < 0 || ctext_size != m_total + tag_size) {
    1007           0 :                         TALLOC_FREE(ptext);
    1008           0 :                         TALLOC_FREE(ctext);
    1009           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1010           0 :                         goto out;
    1011             :                 }
    1012             : 
    1013        8436 :                 len = 0;
    1014       32932 :                 for (i = 1; i < count; i++) {
    1015       24496 :                         if (vector[i].iov_base != NULL) {
    1016       44048 :                                 memcpy(vector[i].iov_base,
    1017       22024 :                                        ctext + len,
    1018       22024 :                                        vector[i].iov_len);
    1019             :                         }
    1020             : 
    1021       24496 :                         len += vector[i].iov_len;
    1022             :                 }
    1023             : 
    1024        8436 :                 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
    1025             : 
    1026        8436 :                 TALLOC_FREE(ptext);
    1027        8436 :                 TALLOC_FREE(ctext);
    1028             :         }
    1029             : 
    1030       10095 :         DBG_INFO("Encrypted SMB2 message\n");
    1031             : 
    1032       10095 :         status = NT_STATUS_OK;
    1033       10095 : out:
    1034       10095 :         return status;
    1035             : }
    1036             : 
    1037       10080 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
    1038             :                                   struct iovec *vector,
    1039             :                                   int count)
    1040             : {
    1041             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
    1042        1657 :         bool use_encryptv2 = false;
    1043             : #endif
    1044             :         uint16_t cipher_id;
    1045             :         uint8_t *tf;
    1046             :         uint16_t flags;
    1047             :         size_t a_total;
    1048             :         ssize_t m_total;
    1049       10080 :         uint32_t msg_size = 0;
    1050       10080 :         uint32_t iv_size = 0;
    1051       10080 :         uint32_t key_size = 0;
    1052       10080 :         size_t tag_size = 0;
    1053       10080 :         gnutls_cipher_algorithm_t algo = 0;
    1054             :         gnutls_datum_t key;
    1055             :         gnutls_datum_t iv;
    1056             :         NTSTATUS status;
    1057             :         int rc;
    1058             : 
    1059       10080 :         if (count < 1) {
    1060           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1061             :         }
    1062             : 
    1063       10080 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
    1064           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1065             :         }
    1066             : 
    1067       10080 :         tf = (uint8_t *)vector[0].iov_base;
    1068             : 
    1069       10080 :         if (!smb2_signing_key_valid(decryption_key)) {
    1070           0 :                 DBG_WARNING("No decryption key for SMB2 signing\n");
    1071           0 :                 return NT_STATUS_ACCESS_DENIED;
    1072             :         }
    1073       10080 :         cipher_id = decryption_key->cipher_algo_id;
    1074             : 
    1075       10080 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
    1076             : 
    1077       10080 :         m_total = iov_buflen(&vector[1], count-1);
    1078       10080 :         if (m_total == -1) {
    1079           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
    1080             :         }
    1081             : 
    1082       10080 :         flags = SVAL(tf, SMB2_TF_FLAGS);
    1083       10080 :         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
    1084             : 
    1085       10080 :         if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
    1086           0 :                 return NT_STATUS_ACCESS_DENIED;
    1087             :         }
    1088             : 
    1089       10080 :         if (msg_size != m_total) {
    1090           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1091             :         }
    1092             : 
    1093       10080 :         switch (cipher_id) {
    1094        1116 :         case SMB2_ENCRYPTION_AES128_CCM:
    1095        1116 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
    1096        1116 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
    1097             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
    1098         318 :                 use_encryptv2 = true;
    1099             : #endif
    1100        1116 :                 break;
    1101        8604 :         case SMB2_ENCRYPTION_AES128_GCM:
    1102        8604 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
    1103        8604 :                 iv_size = gnutls_cipher_get_iv_size(algo);
    1104             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
    1105        1231 :                 use_encryptv2 = true;
    1106             : #endif
    1107        8604 :                 break;
    1108         180 :         case SMB2_ENCRYPTION_AES256_CCM:
    1109         180 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
    1110         180 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
    1111             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
    1112          54 :                 use_encryptv2 = true;
    1113             : #endif
    1114         180 :                 break;
    1115         180 :         case SMB2_ENCRYPTION_AES256_GCM:
    1116         180 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
    1117         180 :                 iv_size = gnutls_cipher_get_iv_size(algo);
    1118             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
    1119          54 :                 use_encryptv2 = true;
    1120             : #endif
    1121         180 :                 break;
    1122           0 :         default:
    1123           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1124             :         }
    1125             : 
    1126       10080 :         key_size = gnutls_cipher_get_key_size(algo);
    1127       10080 :         tag_size = gnutls_cipher_get_tag_size(algo);
    1128             : 
    1129       10080 :         if (key_size != decryption_key->blob.length) {
    1130           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1131             :         }
    1132             : 
    1133       10080 :         if (tag_size != 16) {
    1134           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1135             :         }
    1136             : 
    1137       10080 :         key = (gnutls_datum_t) {
    1138       10080 :                 .data = decryption_key->blob.data,
    1139             :                 .size = key_size,
    1140             :         };
    1141             : 
    1142       10080 :         iv = (gnutls_datum_t) {
    1143       10080 :                 .data = tf + SMB2_TF_NONCE,
    1144             :                 .size = iv_size,
    1145             :         };
    1146             : 
    1147       10080 :         if (decryption_key->cipher_hnd == NULL) {
    1148        1026 :                 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
    1149             :                                              algo,
    1150             :                                              &key);
    1151        1026 :                 if (rc < 0) {
    1152           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1153           0 :                         goto out;
    1154             :                 }
    1155             :         }
    1156             : 
    1157             : /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
    1158             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
    1159        1657 :         if (use_encryptv2) {
    1160             :                 giovec_t auth_iov[1];
    1161             : 
    1162        1657 :                 auth_iov[0] = (giovec_t) {
    1163        1657 :                         .iov_base = tf + SMB2_TF_NONCE,
    1164             :                         .iov_len  = a_total,
    1165             :                 };
    1166             : 
    1167        1657 :                 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
    1168        1657 :                                                   iv.data,
    1169        1657 :                                                   iv.size,
    1170             :                                                   auth_iov,
    1171             :                                                   1,
    1172        1657 :                                                   &vector[1],
    1173             :                                                   count - 1,
    1174        1657 :                                                   tf + SMB2_TF_SIGNATURE,
    1175             :                                                   tag_size);
    1176        1657 :                 if (rc < 0) {
    1177           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1178           0 :                         goto out;
    1179             :                 }
    1180             :         } else
    1181             : #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
    1182             :         {
    1183        8423 :                 size_t ctext_size = m_total + tag_size;
    1184        8423 :                 uint8_t *ctext = NULL;
    1185        8423 :                 size_t ptext_size = m_total;
    1186        8423 :                 uint8_t *ptext = NULL;
    1187        8423 :                 size_t len = 0;
    1188             :                 int i;
    1189        8423 :                 TALLOC_CTX *tmp_ctx = NULL;
    1190             : 
    1191             :                 /*
    1192             :                  * If we come from python bindings, we don't have a stackframe
    1193             :                  * around, so use the NULL context.
    1194             :                  *
    1195             :                  * This is fine as we make sure we free the memory.
    1196             :                  */
    1197        8423 :                 if (talloc_stackframe_exists()) {
    1198        8423 :                         tmp_ctx = talloc_tos();
    1199             :                 }
    1200             : 
    1201             :                 /* GnuTLS doesn't have a iovec API for decryption yet */
    1202             : 
    1203        8423 :                 ptext = talloc_size(tmp_ctx, ptext_size);
    1204        8423 :                 if (ptext == NULL) {
    1205           0 :                         status = NT_STATUS_NO_MEMORY;
    1206           0 :                         goto out;
    1207             :                 }
    1208             : 
    1209        8423 :                 ctext = talloc_size(tmp_ctx, ctext_size);
    1210        8423 :                 if (ctext == NULL) {
    1211           0 :                         TALLOC_FREE(ptext);
    1212           0 :                         status = NT_STATUS_NO_MEMORY;
    1213           0 :                         goto out;
    1214             :                 }
    1215             : 
    1216             : 
    1217       16846 :                 for (i = 1; i < count; i++) {
    1218       16846 :                         memcpy(ctext + len,
    1219        8423 :                                vector[i].iov_base,
    1220        8423 :                                vector[i].iov_len);
    1221             : 
    1222        8423 :                         len += vector[i].iov_len;
    1223             :                 }
    1224        8423 :                 if (len != m_total) {
    1225           0 :                         TALLOC_FREE(ptext);
    1226           0 :                         TALLOC_FREE(ctext);
    1227           0 :                         status = NT_STATUS_INTERNAL_ERROR;
    1228           0 :                         goto out;
    1229             :                 }
    1230             : 
    1231        8423 :                 memcpy(ctext + len,
    1232        8423 :                        tf + SMB2_TF_SIGNATURE,
    1233             :                        tag_size);
    1234             : 
    1235             :                 /* This function will verify the tag */
    1236       16846 :                 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
    1237        8423 :                                                 iv.data,
    1238        8423 :                                                 iv.size,
    1239        8423 :                                                 tf + SMB2_TF_NONCE,
    1240             :                                                 a_total,
    1241             :                                                 tag_size,
    1242             :                                                 ctext,
    1243             :                                                 ctext_size,
    1244             :                                                 ptext,
    1245             :                                                 &ptext_size);
    1246        8423 :                 if (rc < 0 || ptext_size != m_total) {
    1247           0 :                         TALLOC_FREE(ptext);
    1248           0 :                         TALLOC_FREE(ctext);
    1249           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1250           0 :                         goto out;
    1251             :                 }
    1252             : 
    1253        8423 :                 len = 0;
    1254       16846 :                 for (i = 1; i < count; i++) {
    1255       16846 :                         memcpy(vector[i].iov_base,
    1256        8423 :                                ptext + len,
    1257        8423 :                                vector[i].iov_len);
    1258             : 
    1259        8423 :                         len += vector[i].iov_len;
    1260             :                 }
    1261             : 
    1262        8423 :                 TALLOC_FREE(ptext);
    1263        8423 :                 TALLOC_FREE(ctext);
    1264             :         }
    1265             : 
    1266       10080 :         DBG_INFO("Decrypted SMB2 message\n");
    1267             : 
    1268       10080 :         status = NT_STATUS_OK;
    1269       10080 : out:
    1270       10080 :         return status;
    1271             : }

Generated by: LCOV version 1.13