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