LCOV - code coverage report
Current view: top level - libcli/smb - smb2_signing.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 504 635 79.4 %
Date: 2024-06-13 04:01:37 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       10754 : 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       10754 :         *ds = (struct smb2_signing_derivations) { .signing = NULL, };
      42             : 
      43       10754 :         if (protocol >= PROTOCOL_SMB3_11) {
      44        4876 :                 struct smb2_signing_derivation *d = NULL;
      45             : 
      46        4876 :                 SMB_ASSERT(preauth_hash.length != 0);
      47             : 
      48        4876 :                 d = &ds->__signing;
      49        4876 :                 ds->signing = d;
      50        4876 :                 d->label = data_blob_string_const_null("SMBSigningKey");
      51        4876 :                 d->context = preauth_hash;
      52             : 
      53        4876 :                 d = &ds->__cipher_c2s;
      54        4876 :                 ds->cipher_c2s = d;
      55        4876 :                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
      56        4876 :                 d->context = preauth_hash;
      57             : 
      58        4876 :                 d = &ds->__cipher_s2c;
      59        4876 :                 ds->cipher_s2c = d;
      60        4876 :                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
      61        4876 :                 d->context = preauth_hash;
      62             : 
      63        4876 :                 d = &ds->__application;
      64        4876 :                 ds->application = d;
      65        4876 :                 d->label = data_blob_string_const_null("SMBAppKey");
      66        4876 :                 d->context = preauth_hash;
      67             : 
      68        5878 :         } else if (protocol >= PROTOCOL_SMB3_00) {
      69          16 :                 struct smb2_signing_derivation *d = NULL;
      70             : 
      71          16 :                 d = &ds->__signing;
      72          16 :                 ds->signing = d;
      73          16 :                 d->label = data_blob_string_const_null("SMB2AESCMAC");
      74          16 :                 d->context = data_blob_string_const_null("SmbSign");
      75             : 
      76          16 :                 d = &ds->__cipher_c2s;
      77          16 :                 ds->cipher_c2s = d;
      78          16 :                 d->label = data_blob_string_const_null("SMB2AESCCM");
      79          16 :                 d->context = data_blob_string_const_null("ServerIn ");
      80             : 
      81          16 :                 d = &ds->__cipher_s2c;
      82          16 :                 ds->cipher_s2c = d;
      83          16 :                 d->label = data_blob_string_const_null("SMB2AESCCM");
      84          16 :                 d->context = data_blob_string_const_null("ServerOut");
      85             : 
      86          16 :                 d = &ds->__application;
      87          16 :                 ds->application = d;
      88          16 :                 d->label = data_blob_string_const_null("SMB2APP");
      89          16 :                 d->context = data_blob_string_const_null("SmbRpc");
      90             :         }
      91       10754 : }
      92             : 
      93       69126 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
      94             : {
      95       69126 :         if (key->hmac_hnd != NULL) {
      96        5990 :                 gnutls_hmac_deinit(key->hmac_hnd, NULL);
      97        5990 :                 key->hmac_hnd = NULL;
      98             :         }
      99             : 
     100       69126 :         if (key->cipher_hnd != NULL) {
     101        5350 :                 gnutls_aead_cipher_deinit(key->cipher_hnd);
     102        5350 :                 key->cipher_hnd = NULL;
     103             :         }
     104             : 
     105       69126 :         return 0;
     106             : }
     107             : 
     108       11350 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
     109             :                                const struct smb2_signing_key *src,
     110             :                                struct smb2_signing_key **_dst)
     111             : {
     112       11350 :         struct smb2_signing_key *dst = NULL;
     113             : 
     114       11350 :         dst = talloc_zero(mem_ctx, struct smb2_signing_key);
     115       11350 :         if (dst == NULL) {
     116           0 :                 return NT_STATUS_NO_MEMORY;
     117             :         }
     118       11350 :         talloc_set_destructor(dst, smb2_signing_key_destructor);
     119             : 
     120       11350 :         dst->sign_algo_id = src->sign_algo_id;
     121       11350 :         dst->cipher_algo_id = src->cipher_algo_id;
     122             : 
     123       11350 :         if (src->blob.length == 0) {
     124           0 :                 *_dst = dst;
     125           0 :                 return NT_STATUS_OK;
     126             :         }
     127             : 
     128       11350 :         dst->blob = data_blob_talloc_zero(dst, src->blob.length);
     129       11350 :         if (dst->blob.length == 0) {
     130           0 :                 TALLOC_FREE(dst);
     131           0 :                 return NT_STATUS_NO_MEMORY;
     132             :         }
     133       11350 :         talloc_keep_secret(dst->blob.data);
     134       11350 :         memcpy(dst->blob.data, src->blob.data, dst->blob.length);
     135             : 
     136       11350 :         *_dst = dst;
     137       11350 :         return NT_STATUS_OK;
     138             : }
     139             : 
     140       58882 : 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       58882 :         struct smb2_signing_key *key = NULL;
     148       58882 :         size_t in_key_length = 16;
     149       58882 :         size_t out_key_length = 16;
     150             :         NTSTATUS status;
     151             : 
     152       58882 :         if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
     153       42258 :                 SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
     154             :         }
     155       58882 :         if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
     156       16624 :                 SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
     157             :         }
     158             : 
     159       58882 :         key = talloc_zero(mem_ctx, struct smb2_signing_key);
     160       58882 :         if (key == NULL) {
     161           0 :                 return NT_STATUS_NO_MEMORY;
     162             :         }
     163       58882 :         talloc_set_destructor(key, smb2_signing_key_destructor);
     164             : 
     165       58882 :         key->sign_algo_id = sign_algo_id;
     166       58882 :         key->cipher_algo_id = cipher_algo_id;
     167             : 
     168       58882 :         if (master_key == NULL) {
     169       20924 :                 SMB_ASSERT(d == NULL);
     170             : 
     171       20924 :                 *_key = key;
     172       20924 :                 return NT_STATUS_OK;
     173             :         }
     174             : 
     175             :         /*
     176             :          * Per default use the full key.
     177             :          */
     178       37958 :         in_key_length = out_key_length = master_key->length;
     179       37958 :         switch (sign_algo_id) {
     180       16442 :         case SMB2_SIGNING_INVALID_ALGO:
     181             :                 /*
     182             :                  * This means we're processing cipher_algo_id below
     183             :                  */
     184       16442 :                 break;
     185          28 :         case SMB2_SIGNING_MD5_SMB1:
     186          28 :                 SMB_ASSERT(d == NULL);
     187          28 :                 break;
     188       21488 :         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       21488 :                 in_key_length = out_key_length = 16;
     199       21488 :                 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       37958 :         switch (cipher_algo_id) {
     205       21516 :         case SMB2_ENCRYPTION_INVALID_ALGO:
     206             :                 /*
     207             :                  * This means we're processing sign_algo_id above
     208             :                  */
     209       21516 :                 break;
     210        7410 :         case SMB2_ENCRYPTION_NONE:
     211             :                 /*
     212             :                  * No encryption negotiated.
     213             :                  */
     214        7410 :                 break;
     215        9016 :         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        9016 :                 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        9016 :                 in_key_length = out_key_length = 16;
     227        9016 :                 break;
     228          16 :         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          16 :                 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          16 :                 out_key_length = 32;
     240          16 :                 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       37958 :         if (out_key_length == 0) {
     247           0 :                 *_key = key;
     248           0 :                 return NT_STATUS_OK;
     249             :         }
     250             : 
     251       37958 :         key->blob = data_blob_talloc_zero(key, out_key_length);
     252       37958 :         if (key->blob.length == 0) {
     253           0 :                 TALLOC_FREE(key);
     254           0 :                 return NT_STATUS_NO_MEMORY;
     255             :         }
     256       37958 :         talloc_keep_secret(key->blob.data);
     257       37958 :         memcpy(key->blob.data,
     258       37958 :                master_key->data,
     259       37958 :                MIN(key->blob.length, master_key->length));
     260             : 
     261       37958 :         if (d == NULL) {
     262       19144 :                 *_key = key;
     263       19144 :                 return NT_STATUS_OK;
     264             :         }
     265             : 
     266       47078 :         status = smb2_key_derivation(key->blob.data, in_key_length,
     267       18814 :                                      d->label.data, d->label.length,
     268       18814 :                                      d->context.data, d->context.length,
     269             :                                      key->blob.data, out_key_length);
     270       18814 :         if (!NT_STATUS_IS_OK(status)) {
     271           0 :                 TALLOC_FREE(key);
     272           0 :                 return status;
     273             :         }
     274             : 
     275       18814 :         *_key = key;
     276       18814 :         return NT_STATUS_OK;
     277             : }
     278             : 
     279       42258 : 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       42258 :         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       16624 : 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       16624 :         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     3400784 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
     308             : {
     309     3400784 :         if (key == NULL) {
     310       37624 :                 return false;
     311             :         }
     312             : 
     313     3363160 :         if (key->blob.length == 0 || key->blob.data == NULL) {
     314       48840 :                 return false;
     315             :         }
     316             : 
     317     3314320 :         return true;
     318             : }
     319             : 
     320      233438 : 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      233438 :         size_t tag_size = _tag_size;
     326             :         int rc;
     327             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
     328             : 
     329       28667 :         rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
     330             :                                           iv, iv_size,
     331             :                                           auth_iov, auth_iovcnt,
     332             :                                           NULL, 0,
     333             :                                           tag, &tag_size);
     334       28667 :         if (rc < 0) {
     335           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     336             :         }
     337             : 
     338       28667 :         return NT_STATUS_OK;
     339             : #else /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
     340      204771 :         TALLOC_CTX *tmp_ctx = NULL;
     341      204771 :         size_t atext_size = 0;
     342      204771 :         uint8_t *atext = NULL;
     343      204771 :         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      204771 :         if (talloc_stackframe_exists()) {
     353      204640 :                 tmp_ctx = talloc_tos();
     354             :         }
     355             : 
     356     1021502 :         for (i=0; i < auth_iovcnt; i++) {
     357      816731 :                 atext_size += auth_iov[i].iov_len;
     358             :         }
     359             : 
     360      204771 :         atext = talloc_size(tmp_ctx, atext_size);
     361      204771 :         if (atext == NULL) {
     362           0 :                 return NT_STATUS_NO_MEMORY;
     363             :         }
     364             : 
     365     1021502 :         for (i = 0; i < auth_iovcnt; i++) {
     366     1633462 :                 memcpy(atext + len,
     367      816731 :                        auth_iov[i].iov_base,
     368      816731 :                        auth_iov[i].iov_len);
     369             : 
     370      816731 :                 len += auth_iov[i].iov_len;
     371      816731 :                 if (len > atext_size) {
     372           0 :                         TALLOC_FREE(atext);
     373           0 :                         return NT_STATUS_INTERNAL_ERROR;
     374             :                 }
     375             :         }
     376             : 
     377      204771 :         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      204771 :         TALLOC_FREE(atext);
     385      204771 :         if (rc < 0) {
     386           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     387             :         }
     388             : 
     389      204771 :         return NT_STATUS_OK;
     390             : #endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
     391             : }
     392             : 
     393     1317980 : 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     1317980 :         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     1317980 :         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     1317980 :         SMB_ASSERT(count >= 2);
     415     1317980 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     416     1317980 :         SMB_ASSERT(count <= 4);
     417             : 
     418     1317980 :         opcode = SVAL(hdr, SMB2_HDR_OPCODE);
     419     1317980 :         flags = IVAL(hdr, SMB2_HDR_FLAGS);
     420     1317980 :         if (flags & SMB2_HDR_FLAG_REDIRECT) {
     421      662303 :                 NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
     422      662303 :                 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      662303 :                 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     1317980 :         msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
     432     1317980 :         if (msg_id == 0) {
     433          10 :                 if (opcode != SMB2_OP_CANCEL ||
     434             :                     sign_algo_id >= SMB2_SIGNING_AES128_GMAC)
     435             :                 {
     436           0 :                         DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
     437           0 :                         return NT_STATUS_INTERNAL_ERROR;
     438             :                 }
     439             :                 /*
     440             :                  * Legacy algorithms allow MID 0
     441             :                  * for cancel requests
     442             :                  */
     443             :         }
     444     1317980 :         if (msg_id == UINT64_MAX) {
     445           0 :                 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
     446           0 :                 return NT_STATUS_INTERNAL_ERROR;
     447             :         }
     448             : 
     449     1317980 :         switch (sign_algo_id) {
     450      233438 :         case SMB2_SIGNING_AES128_GMAC: {
     451      233438 :                 gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
     452      233438 :                 uint32_t key_size = gnutls_cipher_get_key_size(algo);
     453      233438 :                 uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
     454      233438 :                 size_t tag_size = gnutls_cipher_get_tag_size(algo);
     455      438209 :                 gnutls_datum_t key = {
     456      233438 :                         .data = signing_key->blob.data,
     457      233438 :                         .size = MIN(signing_key->blob.length, key_size),
     458             :                 };
     459      233438 :                 uint64_t high_bits = 0;
     460      233438 :                 uint8_t iv[AES_BLOCK_SIZE] = {0};
     461      233438 :                 giovec_t auth_iov[count+1];
     462      233438 :                 size_t auth_iovcnt = 0;
     463             :                 NTSTATUS status;
     464             :                 int rc;
     465             : 
     466      233438 :                 high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
     467      233438 :                 if (opcode == SMB2_OP_CANCEL) {
     468           8 :                         high_bits |= SMB2_HDR_FLAG_ASYNC;
     469             :                 }
     470      233438 :                 SBVAL(iv, 0, msg_id);
     471      233438 :                 SBVAL(iv, 8, high_bits);
     472             : 
     473      233438 :                 if (signing_key->cipher_hnd == NULL) {
     474        4600 :                         rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
     475             :                                                      algo,
     476             :                                                      &key);
     477        4600 :                         if (rc < 0) {
     478           0 :                                 return gnutls_error_to_ntstatus(rc,
     479             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     480             :                         }
     481             :                 }
     482             : 
     483      233438 :                 SMB_ASSERT(key_size == 16);
     484      233438 :                 SMB_ASSERT(iv_size == 12);
     485      233438 :                 SMB_ASSERT(tag_size == 16);
     486             : 
     487      233438 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     488             :                         .iov_base = discard_const_p(uint8_t, hdr),
     489             :                         .iov_len  = SMB2_HDR_SIGNATURE,
     490             :                 };
     491      233438 :                 auth_iov[auth_iovcnt++] = (giovec_t) {
     492             :                         .iov_base = discard_const_p(uint8_t, zero_sig),
     493             :                         .iov_len  = 16,
     494             :                 };
     495      697235 :                 for (i=1; i < count; i++) {
     496      870986 :                         auth_iov[auth_iovcnt++] = (giovec_t) {
     497      463797 :                                 .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
     498      463797 :                                 .iov_len  = vector[i].iov_len,
     499             :                         };
     500             :                 }
     501             : 
     502      233438 :                 status = smb2_signing_gmac(signing_key->cipher_hnd,
     503             :                                            iv,
     504             :                                            iv_size,
     505             :                                            auth_iov,
     506             :                                            auth_iovcnt,
     507             :                                            signature,
     508             :                                            tag_size);
     509      233438 :                 if (!NT_STATUS_IS_OK(status)) {
     510           0 :                         return status;
     511             :                 }
     512             : 
     513      233438 :                 return NT_STATUS_OK;
     514             :         }       break;
     515             : 
     516         606 :         case SMB2_SIGNING_AES128_CMAC:
     517             : #ifdef HAVE_GNUTLS_AES_CMAC
     518         303 :                 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
     519         303 :                 break;
     520             : #else /* NOT HAVE_GNUTLS_AES_CMAC */
     521             :         {
     522             :                 struct aes_cmac_128_context ctx;
     523         303 :                 uint8_t key[AES_BLOCK_SIZE] = {0};
     524             : 
     525         606 :                 memcpy(key,
     526         303 :                        signing_key->blob.data,
     527         303 :                        MIN(signing_key->blob.length, 16));
     528             : 
     529         303 :                 aes_cmac_128_init(&ctx, key);
     530         303 :                 aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
     531         303 :                 aes_cmac_128_update(&ctx, zero_sig, 16);
     532         908 :                 for (i=1; i < count; i++) {
     533        1210 :                         aes_cmac_128_update(&ctx,
     534         605 :                                         (const uint8_t *)vector[i].iov_base,
     535         605 :                                         vector[i].iov_len);
     536             :                 }
     537         303 :                 aes_cmac_128_final(&ctx, signature);
     538             : 
     539         303 :                 ZERO_ARRAY(key);
     540             : 
     541         303 :                 return NT_STATUS_OK;
     542             :         }       break;
     543             : #endif
     544     1083936 :         case SMB2_SIGNING_HMAC_SHA256:
     545     1083936 :                 hmac_algo = GNUTLS_MAC_SHA256;
     546     1083936 :                 break;
     547             : 
     548           0 :         default:
     549           0 :                 return NT_STATUS_HMAC_NOT_SUPPORTED;
     550             :         }
     551             : 
     552     1084239 :         if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
     553     1084239 :                 uint8_t digest[gnutls_hash_get_len(hmac_algo)];
     554     2055185 :                 gnutls_datum_t key = {
     555     1084239 :                         .data = signing_key->blob.data,
     556     1084239 :                         .size = MIN(signing_key->blob.length, 16),
     557             :                 };
     558             :                 int rc;
     559             : 
     560     1084239 :                 if (signing_key->hmac_hnd == NULL) {
     561       10059 :                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
     562             :                                               hmac_algo,
     563        6002 :                                               key.data,
     564        6002 :                                               key.size);
     565        6002 :                         if (rc < 0) {
     566           0 :                                 return gnutls_error_to_ntstatus(rc,
     567             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     568             :                         }
     569             :                 }
     570             : 
     571     1084239 :                 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
     572     1084239 :                 if (rc < 0) {
     573           0 :                         return gnutls_error_to_ntstatus(rc,
     574             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     575             :                 }
     576     1084239 :                 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
     577     1084239 :                 if (rc < 0) {
     578           0 :                         return gnutls_error_to_ntstatus(rc,
     579             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     580             :                 }
     581             : 
     582     3241291 :                 for (i = 1; i < count; i++) {
     583     4089095 :                         rc = gnutls_hmac(signing_key->hmac_hnd,
     584     2157052 :                                          vector[i].iov_base,
     585     2157052 :                                          vector[i].iov_len);
     586     2157052 :                         if (rc < 0) {
     587           0 :                                 return gnutls_error_to_ntstatus(rc,
     588             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     589             :                         }
     590             :                 }
     591     1084239 :                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
     592     1084239 :                 memcpy(signature, digest, 16);
     593     1084239 :                 ZERO_ARRAY(digest);
     594     1084239 :                 return NT_STATUS_OK;
     595             :         }
     596             : 
     597           0 :         return NT_STATUS_HMAC_NOT_SUPPORTED;
     598             : }
     599             : 
     600      660070 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
     601             :                                struct iovec *vector,
     602             :                                int count)
     603             : {
     604             :         uint16_t sign_algo_id;
     605             :         uint8_t *hdr;
     606             :         uint64_t session_id;
     607             :         uint8_t res[16];
     608             :         NTSTATUS status;
     609             : 
     610             :         /*
     611             :          * We expect
     612             :          * - SMB2 HDR
     613             :          * - SMB2 BODY FIXED
     614             :          * - (optional) SMB2 BODY DYN
     615             :          * - (optional) PADDING
     616             :          */
     617      660070 :         SMB_ASSERT(count >= 2);
     618      660070 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     619      660070 :         SMB_ASSERT(count <= 4);
     620             : 
     621      660070 :         hdr = (uint8_t *)vector[0].iov_base;
     622             : 
     623      660070 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     624      660070 :         if (session_id == 0) {
     625             :                 /*
     626             :                  * do not sign messages with a zero session_id.
     627             :                  * See MS-SMB2 3.2.4.1.1
     628             :                  */
     629           0 :                 return NT_STATUS_OK;
     630             :         }
     631             : 
     632      660070 :         if (!smb2_signing_key_valid(signing_key)) {
     633           0 :                 DBG_WARNING("No signing key for SMB2 signing\n");
     634           0 :                 return NT_STATUS_ACCESS_DENIED;
     635             :         }
     636             : 
     637      660070 :         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
     638             : 
     639      660070 :         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
     640             : 
     641      660070 :         sign_algo_id = signing_key->sign_algo_id;
     642             : 
     643      660070 :         status = smb2_signing_calc_signature(signing_key,
     644             :                                              sign_algo_id,
     645             :                                              vector,
     646             :                                              count,
     647             :                                              res);
     648      660070 :         if (!NT_STATUS_IS_OK(status)) {
     649           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     650             :                         (unsigned)sign_algo_id, nt_errstr(status));
     651           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     652           0 :                         smb_panic(__location__);
     653             :                 }
     654           0 :                 return status;
     655             :         }
     656             : 
     657      660070 :         DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
     658             :                  (unsigned)sign_algo_id));
     659             : 
     660      660070 :         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
     661             : 
     662      660070 :         return NT_STATUS_OK;
     663             : }
     664             : 
     665      657910 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
     666             :                                 const struct iovec *vector,
     667             :                                 int count)
     668             : {
     669             :         uint16_t sign_algo_id;
     670             :         const uint8_t *hdr;
     671             :         const uint8_t *sig;
     672             :         uint64_t session_id;
     673             :         uint8_t res[16];
     674             :         NTSTATUS status;
     675             : 
     676             :         /*
     677             :          * We expect
     678             :          * - SMB2 HDR
     679             :          * - SMB2 BODY FIXED
     680             :          * - (optional) SMB2 BODY DYN
     681             :          * - (optional) PADDING
     682             :          */
     683      657910 :         SMB_ASSERT(count >= 2);
     684      657910 :         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
     685      657910 :         SMB_ASSERT(count <= 4);
     686             : 
     687      657910 :         hdr = (const uint8_t *)vector[0].iov_base;
     688             : 
     689      657910 :         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
     690      657910 :         if (session_id == 0) {
     691             :                 /*
     692             :                  * do not sign messages with a zero session_id.
     693             :                  * See MS-SMB2 3.2.4.1.1
     694             :                  */
     695           0 :                 return NT_STATUS_OK;
     696             :         }
     697             : 
     698      657910 :         if (!smb2_signing_key_valid(signing_key)) {
     699             :                 /* we don't have the session key yet */
     700           0 :                 return NT_STATUS_OK;
     701             :         }
     702             : 
     703      657910 :         sig = hdr+SMB2_HDR_SIGNATURE;
     704             : 
     705      657910 :         sign_algo_id = signing_key->sign_algo_id;
     706             : 
     707      657910 :         status = smb2_signing_calc_signature(signing_key,
     708             :                                              sign_algo_id,
     709             :                                              vector,
     710             :                                              count,
     711             :                                              res);
     712      657910 :         if (!NT_STATUS_IS_OK(status)) {
     713           0 :                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
     714             :                         (unsigned)sign_algo_id, nt_errstr(status));
     715           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
     716           0 :                         status = NT_STATUS_ACCESS_DENIED;
     717             :                 }
     718           0 :                 return status;
     719             :         }
     720             : 
     721      657910 :         if (!mem_equal_const_time(res, sig, 16)) {
     722          46 :                 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
     723             :                          (unsigned)sign_algo_id));
     724          46 :                 dump_data(0, sig, 16);
     725          46 :                 dump_data(0, res, 16);
     726          46 :                 return NT_STATUS_ACCESS_DENIED;
     727             :         }
     728             : 
     729      657864 :         return NT_STATUS_OK;
     730             : }
     731             : 
     732       18830 : NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
     733             :                              const uint8_t *Label, size_t Label_len,
     734             :                              const uint8_t *Context, size_t Context_len,
     735             :                              uint8_t *KO, size_t KO_len)
     736       18830 : {
     737       18830 :         gnutls_hmac_hd_t hmac_hnd = NULL;
     738             :         uint8_t buf[4];
     739             :         static const uint8_t zero = 0;
     740       18830 :         const size_t digest_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
     741       18830 :         uint8_t digest[digest_len];
     742       18830 :         uint32_t i = 1;
     743       18830 :         uint32_t L = KO_len * 8;
     744             :         int rc;
     745             : 
     746       18830 :         if (KO_len > digest_len) {
     747           0 :                 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len, digest_len);
     748           0 :                 return NT_STATUS_INTERNAL_ERROR;
     749             :         }
     750             : 
     751       18830 :         switch (KO_len) {
     752       18830 :         case 16:
     753             :         case 32:
     754       18830 :                 break;
     755           0 :         default:
     756           0 :                 DBG_ERR("KO_len[%zu] not supported\n", KO_len);
     757           0 :                 return NT_STATUS_INTERNAL_ERROR;
     758             :         }
     759             : 
     760             :         /*
     761             :          * a simplified version of
     762             :          * "NIST Special Publication 800-108" section 5.1
     763             :          * using hmac-sha256.
     764             :          */
     765       18830 :         rc = gnutls_hmac_init(&hmac_hnd,
     766             :                               GNUTLS_MAC_SHA256,
     767             :                               KI,
     768             :                               KI_len);
     769       18830 :         if (rc < 0) {
     770           0 :                 return gnutls_error_to_ntstatus(rc,
     771             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     772             :         }
     773             : 
     774       18830 :         RSIVAL(buf, 0, i);
     775       18830 :         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
     776       18830 :         if (rc < 0) {
     777           0 :                 return gnutls_error_to_ntstatus(rc,
     778             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     779             :         }
     780       18830 :         rc = gnutls_hmac(hmac_hnd, Label, Label_len);
     781       18830 :         if (rc < 0) {
     782           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     783           0 :                 return gnutls_error_to_ntstatus(rc,
     784             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     785             :         }
     786       18830 :         rc = gnutls_hmac(hmac_hnd, &zero, 1);
     787       18830 :         if (rc < 0) {
     788           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     789           0 :                 return gnutls_error_to_ntstatus(rc,
     790             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     791             :         }
     792       18830 :         rc = gnutls_hmac(hmac_hnd, Context, Context_len);
     793       18830 :         if (rc < 0) {
     794           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     795           0 :                 return gnutls_error_to_ntstatus(rc,
     796             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     797             :         }
     798       18830 :         RSIVAL(buf, 0, L);
     799       18830 :         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
     800       18830 :         if (rc < 0) {
     801           0 :                 gnutls_hmac_deinit(hmac_hnd, NULL);
     802           0 :                 return gnutls_error_to_ntstatus(rc,
     803             :                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
     804             :         }
     805             : 
     806       18830 :         gnutls_hmac_deinit(hmac_hnd, digest);
     807             : 
     808       18830 :         memcpy(KO, digest, KO_len);
     809             : 
     810       18830 :         ZERO_ARRAY(digest);
     811             : 
     812       18830 :         return NT_STATUS_OK;
     813             : }
     814             : 
     815        1259 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
     816             :                                   struct iovec *vector,
     817             :                                   int count)
     818             : {
     819             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
     820         629 :         bool use_encryptv2 = false;
     821             : #endif
     822             :         uint16_t cipher_id;
     823             :         uint8_t *tf;
     824             :         size_t a_total;
     825             :         ssize_t m_total;
     826        1259 :         uint32_t iv_size = 0;
     827        1259 :         uint32_t key_size = 0;
     828        1259 :         size_t tag_size = 0;
     829        1259 :         gnutls_cipher_algorithm_t algo = 0;
     830             :         gnutls_datum_t key;
     831             :         gnutls_datum_t iv;
     832             :         NTSTATUS status;
     833             :         int rc;
     834             : 
     835        1259 :         if (count < 1) {
     836           0 :                 return NT_STATUS_INVALID_PARAMETER;
     837             :         }
     838             : 
     839        1259 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
     840           0 :                 return NT_STATUS_INVALID_PARAMETER;
     841             :         }
     842             : 
     843        1259 :         tf = (uint8_t *)vector[0].iov_base;
     844             : 
     845        1259 :         if (!smb2_signing_key_valid(encryption_key)) {
     846           0 :                 DBG_WARNING("No encryption key for SMB2 signing\n");
     847           0 :                 return NT_STATUS_ACCESS_DENIED;
     848             :         }
     849        1259 :         cipher_id = encryption_key->cipher_algo_id;
     850             : 
     851        1259 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
     852             : 
     853        1259 :         m_total = iov_buflen(&vector[1], count-1);
     854        1259 :         if (m_total == -1) {
     855           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     856             :         }
     857             : 
     858        1259 :         SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
     859        1259 :         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
     860             : 
     861        1259 :         switch (cipher_id) {
     862         212 :         case SMB2_ENCRYPTION_AES128_CCM:
     863         212 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
     864         212 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     865             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     866         106 :                 use_encryptv2 = true;
     867             : #endif
     868         212 :                 break;
     869         975 :         case SMB2_ENCRYPTION_AES128_GCM:
     870         975 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
     871         975 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     872             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
     873         487 :                 use_encryptv2 = true;
     874             : #endif
     875         975 :                 break;
     876          36 :         case SMB2_ENCRYPTION_AES256_CCM:
     877          36 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
     878          36 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
     879             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
     880          18 :                 use_encryptv2 = true;
     881             : #endif
     882          36 :                 break;
     883          36 :         case SMB2_ENCRYPTION_AES256_GCM:
     884          36 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
     885          36 :                 iv_size = gnutls_cipher_get_iv_size(algo);
     886             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
     887          18 :                 use_encryptv2 = true;
     888             : #endif
     889          36 :                 break;
     890           0 :         default:
     891           0 :                 return NT_STATUS_INVALID_PARAMETER;
     892             :         }
     893             : 
     894        1259 :         key_size = gnutls_cipher_get_key_size(algo);
     895        1259 :         tag_size = gnutls_cipher_get_tag_size(algo);
     896             : 
     897        1259 :         if (key_size != encryption_key->blob.length) {
     898           0 :                 return NT_STATUS_INTERNAL_ERROR;
     899             :         }
     900             : 
     901        1259 :         if (tag_size != 16) {
     902           0 :                 return NT_STATUS_INTERNAL_ERROR;
     903             :         }
     904             : 
     905        1259 :         key = (gnutls_datum_t) {
     906        1259 :                 .data = encryption_key->blob.data,
     907             :                 .size = key_size,
     908             :         };
     909             : 
     910        1259 :         iv = (gnutls_datum_t) {
     911        1259 :                 .data = tf + SMB2_TF_NONCE,
     912             :                 .size = iv_size,
     913             :         };
     914             : 
     915        1259 :         if (encryption_key->cipher_hnd == NULL) {
     916         700 :                 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
     917             :                                         algo,
     918             :                                         &key);
     919         700 :                 if (rc < 0) {
     920           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     921           0 :                         goto out;
     922             :                 }
     923             :         }
     924             : 
     925        1259 :         memset(tf + SMB2_TF_NONCE + iv_size,
     926             :                0,
     927        1259 :                16 - iv_size);
     928             : 
     929             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
     930         629 :         if (use_encryptv2) {
     931         629 :                 uint8_t tag[tag_size];
     932             :                 giovec_t auth_iov[1];
     933             : 
     934         629 :                 auth_iov[0] = (giovec_t) {
     935         629 :                         .iov_base = tf + SMB2_TF_NONCE,
     936             :                         .iov_len  = a_total,
     937             :                 };
     938             : 
     939         629 :                 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
     940         629 :                                                   iv.data,
     941         629 :                                                   iv.size,
     942             :                                                   auth_iov,
     943             :                                                   1,
     944         629 :                                                   &vector[1],
     945             :                                                   count - 1,
     946             :                                                   tag,
     947             :                                                   &tag_size);
     948         629 :                 if (rc < 0) {
     949           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
     950           0 :                         goto out;
     951             :                 }
     952             : 
     953         629 :                 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
     954             :         } else
     955             : #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
     956             :         {
     957         630 :                 size_t ptext_size = m_total;
     958         630 :                 uint8_t *ptext = NULL;
     959         630 :                 size_t ctext_size = m_total + tag_size;
     960         630 :                 uint8_t *ctext = NULL;
     961         630 :                 size_t len = 0;
     962             :                 int i;
     963         630 :                 TALLOC_CTX *tmp_ctx = NULL;
     964             : 
     965             :                 /*
     966             :                  * If we come from python bindings, we don't have a stackframe
     967             :                  * around, so use the NULL context.
     968             :                  *
     969             :                  * This is fine as we make sure we free the memory.
     970             :                  */
     971         630 :                 if (talloc_stackframe_exists()) {
     972         630 :                         tmp_ctx = talloc_tos();
     973             :                 }
     974             : 
     975         630 :                 ptext = talloc_size(tmp_ctx, ptext_size);
     976         630 :                 if (ptext == NULL) {
     977           0 :                         status = NT_STATUS_NO_MEMORY;
     978           0 :                         goto out;
     979             :                 }
     980             : 
     981         630 :                 ctext = talloc_size(tmp_ctx, ctext_size);
     982         630 :                 if (ctext == NULL) {
     983           0 :                         TALLOC_FREE(ptext);
     984           0 :                         status = NT_STATUS_NO_MEMORY;
     985           0 :                         goto out;
     986             :                 }
     987             : 
     988        2501 :                 for (i = 1; i < count; i++) {
     989        1871 :                         if (vector[i].iov_base != NULL) {
     990        3462 :                                 memcpy(ptext + len,
     991        1731 :                                        vector[i].iov_base,
     992        1731 :                                        vector[i].iov_len);
     993             :                         }
     994             : 
     995        1871 :                         len += vector[i].iov_len;
     996        1871 :                         if (len > ptext_size) {
     997           0 :                                 TALLOC_FREE(ptext);
     998           0 :                                 TALLOC_FREE(ctext);
     999           0 :                                 status = NT_STATUS_INTERNAL_ERROR;
    1000           0 :                                 goto out;
    1001             :                         }
    1002             :                 }
    1003             : 
    1004        1260 :                 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
    1005         630 :                                                 iv.data,
    1006         630 :                                                 iv.size,
    1007         630 :                                                 tf + SMB2_TF_NONCE,
    1008             :                                                 a_total,
    1009             :                                                 tag_size,
    1010             :                                                 ptext,
    1011             :                                                 ptext_size,
    1012             :                                                 ctext,
    1013             :                                                 &ctext_size);
    1014         630 :                 if (rc < 0 || ctext_size != m_total + tag_size) {
    1015           0 :                         TALLOC_FREE(ptext);
    1016           0 :                         TALLOC_FREE(ctext);
    1017           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1018           0 :                         goto out;
    1019             :                 }
    1020             : 
    1021         630 :                 len = 0;
    1022        2501 :                 for (i = 1; i < count; i++) {
    1023        1871 :                         if (vector[i].iov_base != NULL) {
    1024        3462 :                                 memcpy(vector[i].iov_base,
    1025        1731 :                                        ctext + len,
    1026        1731 :                                        vector[i].iov_len);
    1027             :                         }
    1028             : 
    1029        1871 :                         len += vector[i].iov_len;
    1030             :                 }
    1031             : 
    1032         630 :                 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
    1033             : 
    1034         630 :                 TALLOC_FREE(ptext);
    1035         630 :                 TALLOC_FREE(ctext);
    1036             :         }
    1037             : 
    1038        1259 :         DBG_INFO("Encrypted SMB2 message\n");
    1039             : 
    1040        1259 :         status = NT_STATUS_OK;
    1041        1259 : out:
    1042        1259 :         return status;
    1043             : }
    1044             : 
    1045        1259 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
    1046             :                                   struct iovec *vector,
    1047             :                                   int count)
    1048             : {
    1049             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
    1050         629 :         bool use_encryptv2 = false;
    1051             : #endif
    1052             :         uint16_t cipher_id;
    1053             :         uint8_t *tf;
    1054             :         uint16_t flags;
    1055             :         size_t a_total;
    1056             :         ssize_t m_total;
    1057        1259 :         uint32_t msg_size = 0;
    1058        1259 :         uint32_t iv_size = 0;
    1059        1259 :         uint32_t key_size = 0;
    1060        1259 :         size_t tag_size = 0;
    1061        1259 :         gnutls_cipher_algorithm_t algo = 0;
    1062             :         gnutls_datum_t key;
    1063             :         gnutls_datum_t iv;
    1064             :         NTSTATUS status;
    1065             :         int rc;
    1066             : 
    1067        1259 :         if (count < 1) {
    1068           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1069             :         }
    1070             : 
    1071        1259 :         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
    1072           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1073             :         }
    1074             : 
    1075        1259 :         tf = (uint8_t *)vector[0].iov_base;
    1076             : 
    1077        1259 :         if (!smb2_signing_key_valid(decryption_key)) {
    1078           0 :                 DBG_WARNING("No decryption key for SMB2 signing\n");
    1079           0 :                 return NT_STATUS_ACCESS_DENIED;
    1080             :         }
    1081        1259 :         cipher_id = decryption_key->cipher_algo_id;
    1082             : 
    1083        1259 :         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
    1084             : 
    1085        1259 :         m_total = iov_buflen(&vector[1], count-1);
    1086        1259 :         if (m_total == -1) {
    1087           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
    1088             :         }
    1089             : 
    1090        1259 :         flags = SVAL(tf, SMB2_TF_FLAGS);
    1091        1259 :         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
    1092             : 
    1093        1259 :         if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
    1094           0 :                 return NT_STATUS_ACCESS_DENIED;
    1095             :         }
    1096             : 
    1097        1259 :         if (msg_size != m_total) {
    1098           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1099             :         }
    1100             : 
    1101        1259 :         switch (cipher_id) {
    1102         212 :         case SMB2_ENCRYPTION_AES128_CCM:
    1103         212 :                 algo = GNUTLS_CIPHER_AES_128_CCM;
    1104         212 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
    1105             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
    1106         106 :                 use_encryptv2 = true;
    1107             : #endif
    1108         212 :                 break;
    1109         975 :         case SMB2_ENCRYPTION_AES128_GCM:
    1110         975 :                 algo = GNUTLS_CIPHER_AES_128_GCM;
    1111         975 :                 iv_size = gnutls_cipher_get_iv_size(algo);
    1112             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
    1113         487 :                 use_encryptv2 = true;
    1114             : #endif
    1115         975 :                 break;
    1116          36 :         case SMB2_ENCRYPTION_AES256_CCM:
    1117          36 :                 algo = GNUTLS_CIPHER_AES_256_CCM;
    1118          36 :                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
    1119             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
    1120          18 :                 use_encryptv2 = true;
    1121             : #endif
    1122          36 :                 break;
    1123          36 :         case SMB2_ENCRYPTION_AES256_GCM:
    1124          36 :                 algo = GNUTLS_CIPHER_AES_256_GCM;
    1125          36 :                 iv_size = gnutls_cipher_get_iv_size(algo);
    1126             : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
    1127          18 :                 use_encryptv2 = true;
    1128             : #endif
    1129          36 :                 break;
    1130           0 :         default:
    1131           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1132             :         }
    1133             : 
    1134        1259 :         key_size = gnutls_cipher_get_key_size(algo);
    1135        1259 :         tag_size = gnutls_cipher_get_tag_size(algo);
    1136             : 
    1137        1259 :         if (key_size != decryption_key->blob.length) {
    1138           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1139             :         }
    1140             : 
    1141        1259 :         if (tag_size != 16) {
    1142           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1143             :         }
    1144             : 
    1145        1259 :         key = (gnutls_datum_t) {
    1146        1259 :                 .data = decryption_key->blob.data,
    1147             :                 .size = key_size,
    1148             :         };
    1149             : 
    1150        1259 :         iv = (gnutls_datum_t) {
    1151        1259 :                 .data = tf + SMB2_TF_NONCE,
    1152             :                 .size = iv_size,
    1153             :         };
    1154             : 
    1155        1259 :         if (decryption_key->cipher_hnd == NULL) {
    1156         148 :                 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
    1157             :                                              algo,
    1158             :                                              &key);
    1159         148 :                 if (rc < 0) {
    1160           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1161           0 :                         goto out;
    1162             :                 }
    1163             :         }
    1164             : 
    1165             : /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
    1166             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
    1167         629 :         if (use_encryptv2) {
    1168             :                 giovec_t auth_iov[1];
    1169             : 
    1170         629 :                 auth_iov[0] = (giovec_t) {
    1171         629 :                         .iov_base = tf + SMB2_TF_NONCE,
    1172             :                         .iov_len  = a_total,
    1173             :                 };
    1174             : 
    1175         629 :                 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
    1176         629 :                                                   iv.data,
    1177         629 :                                                   iv.size,
    1178             :                                                   auth_iov,
    1179             :                                                   1,
    1180         629 :                                                   &vector[1],
    1181             :                                                   count - 1,
    1182         629 :                                                   tf + SMB2_TF_SIGNATURE,
    1183             :                                                   tag_size);
    1184         629 :                 if (rc < 0) {
    1185           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1186           0 :                         goto out;
    1187             :                 }
    1188             :         } else
    1189             : #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
    1190             :         {
    1191         630 :                 size_t ctext_size = m_total + tag_size;
    1192         630 :                 uint8_t *ctext = NULL;
    1193         630 :                 size_t ptext_size = m_total;
    1194         630 :                 uint8_t *ptext = NULL;
    1195         630 :                 size_t len = 0;
    1196             :                 int i;
    1197         630 :                 TALLOC_CTX *tmp_ctx = NULL;
    1198             : 
    1199             :                 /*
    1200             :                  * If we come from python bindings, we don't have a stackframe
    1201             :                  * around, so use the NULL context.
    1202             :                  *
    1203             :                  * This is fine as we make sure we free the memory.
    1204             :                  */
    1205         630 :                 if (talloc_stackframe_exists()) {
    1206         630 :                         tmp_ctx = talloc_tos();
    1207             :                 }
    1208             : 
    1209             :                 /* GnuTLS doesn't have a iovec API for decryption yet */
    1210             : 
    1211         630 :                 ptext = talloc_size(tmp_ctx, ptext_size);
    1212         630 :                 if (ptext == NULL) {
    1213           0 :                         status = NT_STATUS_NO_MEMORY;
    1214           0 :                         goto out;
    1215             :                 }
    1216             : 
    1217         630 :                 ctext = talloc_size(tmp_ctx, ctext_size);
    1218         630 :                 if (ctext == NULL) {
    1219           0 :                         TALLOC_FREE(ptext);
    1220           0 :                         status = NT_STATUS_NO_MEMORY;
    1221           0 :                         goto out;
    1222             :                 }
    1223             : 
    1224             : 
    1225        1260 :                 for (i = 1; i < count; i++) {
    1226        1260 :                         memcpy(ctext + len,
    1227         630 :                                vector[i].iov_base,
    1228         630 :                                vector[i].iov_len);
    1229             : 
    1230         630 :                         len += vector[i].iov_len;
    1231             :                 }
    1232         630 :                 if (len != m_total) {
    1233           0 :                         TALLOC_FREE(ptext);
    1234           0 :                         TALLOC_FREE(ctext);
    1235           0 :                         status = NT_STATUS_INTERNAL_ERROR;
    1236           0 :                         goto out;
    1237             :                 }
    1238             : 
    1239         630 :                 memcpy(ctext + len,
    1240         630 :                        tf + SMB2_TF_SIGNATURE,
    1241             :                        tag_size);
    1242             : 
    1243             :                 /* This function will verify the tag */
    1244        1260 :                 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
    1245         630 :                                                 iv.data,
    1246         630 :                                                 iv.size,
    1247         630 :                                                 tf + SMB2_TF_NONCE,
    1248             :                                                 a_total,
    1249             :                                                 tag_size,
    1250             :                                                 ctext,
    1251             :                                                 ctext_size,
    1252             :                                                 ptext,
    1253             :                                                 &ptext_size);
    1254         630 :                 if (rc < 0) {
    1255           0 :                         TALLOC_FREE(ptext);
    1256           0 :                         TALLOC_FREE(ctext);
    1257           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1258           0 :                         goto out;
    1259             :                 }
    1260             : #ifdef HAVE_GNUTLS_AEAD_CIPHER_DECRYPT_PTEXT_LEN_BUG
    1261             :                 /*
    1262             :                  * Note that gnutls before 3.5.2 had a bug and returned
    1263             :                  * *ptext_len = ctext_len, instead of
    1264             :                  * *ptext_len = ctext_len - tag_size
    1265             :                  */
    1266             :                 if (ptext_size != ctext_size) {
    1267             :                         TALLOC_FREE(ptext);
    1268             :                         TALLOC_FREE(ctext);
    1269             :                         rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
    1270             :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1271             :                         goto out;
    1272             :                 }
    1273             :                 ptext_size -= tag_size;
    1274             : #endif /* HAVE_GNUTLS_AEAD_CIPHER_DECRYPT_PTEXT_LEN_BUG */
    1275         630 :                 if (ptext_size != m_total) {
    1276           0 :                         TALLOC_FREE(ptext);
    1277           0 :                         TALLOC_FREE(ctext);
    1278           0 :                         rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
    1279           0 :                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
    1280           0 :                         goto out;
    1281             :                 }
    1282             : 
    1283         630 :                 len = 0;
    1284        1260 :                 for (i = 1; i < count; i++) {
    1285        1260 :                         memcpy(vector[i].iov_base,
    1286         630 :                                ptext + len,
    1287         630 :                                vector[i].iov_len);
    1288             : 
    1289         630 :                         len += vector[i].iov_len;
    1290             :                 }
    1291             : 
    1292         630 :                 TALLOC_FREE(ptext);
    1293         630 :                 TALLOC_FREE(ctext);
    1294             :         }
    1295             : 
    1296        1259 :         DBG_INFO("Decrypted SMB2 message\n");
    1297             : 
    1298        1259 :         status = NT_STATUS_OK;
    1299        1259 : out:
    1300        1259 :         return status;
    1301             : }

Generated by: LCOV version 1.13