libcli/smb: no longer pass protocol to smb2_signing_{sign,check}_pdu()
[gd/samba-autobuild/.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_10) {
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_SMB2_24) {
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                 /*
191                  * signing keys are padded or truncated to
192                  * 16 bytes.
193                  *
194                  * Even with master_key->length = 0,
195                  * we need to use 16 zeros.
196                  */
197                 in_key_length = out_key_length = 16;
198                 break;
199         default:
200                 DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id);
201                 return NT_STATUS_HMAC_NOT_SUPPORTED;
202         }
203         switch (cipher_algo_id) {
204         case SMB2_ENCRYPTION_INVALID_ALGO:
205                 /*
206                  * This means we're processing sign_algo_id above
207                  */
208                 break;
209         case SMB2_ENCRYPTION_NONE:
210                 /*
211                  * No encryption negotiated.
212                  */
213                 break;
214         case SMB2_ENCRYPTION_AES128_CCM:
215         case SMB2_ENCRYPTION_AES128_GCM:
216                 /*
217                  * encryption keys are padded or truncated to
218                  * 16 bytes.
219                  */
220                 if (master_key->length == 0) {
221                         DBG_ERR("cipher_algo_id[%u] without key\n",
222                                 cipher_algo_id);
223                         return NT_STATUS_NO_USER_SESSION_KEY;
224                 }
225                 in_key_length = out_key_length = 16;
226                 break;
227         default:
228                 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id);
229                 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG;
230         }
231
232         if (out_key_length == 0) {
233                 *_key = key;
234                 return NT_STATUS_OK;
235         }
236
237         key->blob = data_blob_talloc_zero(key, out_key_length);
238         if (key->blob.length == 0) {
239                 TALLOC_FREE(key);
240                 return NT_STATUS_NO_MEMORY;
241         }
242         talloc_keep_secret(key->blob.data);
243         memcpy(key->blob.data,
244                master_key->data,
245                MIN(key->blob.length, master_key->length));
246
247         if (d == NULL) {
248                 *_key = key;
249                 return NT_STATUS_OK;
250         }
251
252         status = smb2_key_derivation(key->blob.data, in_key_length,
253                                      d->label.data, d->label.length,
254                                      d->context.data, d->context.length,
255                                      key->blob.data, out_key_length);
256         if (!NT_STATUS_IS_OK(status)) {
257                 TALLOC_FREE(key);
258                 return status;
259         }
260
261         *_key = key;
262         return NT_STATUS_OK;
263 }
264
265 NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
266                                       uint16_t sign_algo_id,
267                                       const DATA_BLOB *master_key,
268                                       const struct smb2_signing_derivation *d,
269                                       struct smb2_signing_key **_key)
270 {
271         return smb2_signing_key_create(mem_ctx,
272                                        sign_algo_id,
273                                        SMB2_ENCRYPTION_INVALID_ALGO,
274                                        master_key,
275                                        d,
276                                        _key);
277 }
278
279 NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
280                                         uint16_t cipher_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                                        SMB2_SIGNING_INVALID_ALGO,
287                                        cipher_algo_id,
288                                        master_key,
289                                        d,
290                                        _key);
291 }
292
293 bool smb2_signing_key_valid(const struct smb2_signing_key *key)
294 {
295         if (key == NULL) {
296                 return false;
297         }
298
299         if (key->blob.length == 0 || key->blob.data == NULL) {
300                 return false;
301         }
302
303         return true;
304 }
305
306 static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
307                                             uint16_t sign_algo_id,
308                                             const struct iovec *vector,
309                                             int count,
310                                             uint8_t signature[16])
311 {
312         const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
313         static const uint8_t zero_sig[16] = { 0, };
314         gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
315         int i;
316
317         /*
318          * We expect
319          * - SMB2 HDR
320          * - SMB2 BODY FIXED
321          * - (optional) SMB2 BODY DYN
322          * - (optional) PADDING
323          */
324         SMB_ASSERT(count >= 2);
325         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
326         SMB_ASSERT(count <= 4);
327
328         switch (sign_algo_id) {
329         case SMB2_SIGNING_AES128_CMAC:
330 #ifdef HAVE_GNUTLS_AES_CMAC
331                 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
332                 break;
333 #else /* NOT HAVE_GNUTLS_AES_CMAC */
334         {
335                 struct aes_cmac_128_context ctx;
336                 uint8_t key[AES_BLOCK_SIZE] = {0};
337
338                 memcpy(key,
339                        signing_key->blob.data,
340                        MIN(signing_key->blob.length, 16));
341
342                 aes_cmac_128_init(&ctx, key);
343                 aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
344                 aes_cmac_128_update(&ctx, zero_sig, 16);
345                 for (i=1; i < count; i++) {
346                         aes_cmac_128_update(&ctx,
347                                         (const uint8_t *)vector[i].iov_base,
348                                         vector[i].iov_len);
349                 }
350                 aes_cmac_128_final(&ctx, signature);
351
352                 ZERO_ARRAY(key);
353
354                 return NT_STATUS_OK;
355         }       break;
356 #endif
357         case SMB2_SIGNING_HMAC_SHA256:
358                 hmac_algo = GNUTLS_MAC_SHA256;
359                 break;
360
361         default:
362                 return NT_STATUS_HMAC_NOT_SUPPORTED;
363         }
364
365         if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
366                 uint8_t digest[gnutls_hash_get_len(hmac_algo)];
367                 gnutls_datum_t key = {
368                         .data = signing_key->blob.data,
369                         .size = MIN(signing_key->blob.length, 16),
370                 };
371                 int rc;
372
373                 if (signing_key->hmac_hnd == NULL) {
374                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
375                                               hmac_algo,
376                                               key.data,
377                                               key.size);
378                         if (rc < 0) {
379                                 return gnutls_error_to_ntstatus(rc,
380                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
381                         }
382                 }
383
384                 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
385                 if (rc < 0) {
386                         return gnutls_error_to_ntstatus(rc,
387                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
388                 }
389                 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
390                 if (rc < 0) {
391                         return gnutls_error_to_ntstatus(rc,
392                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
393                 }
394
395                 for (i = 1; i < count; i++) {
396                         rc = gnutls_hmac(signing_key->hmac_hnd,
397                                          vector[i].iov_base,
398                                          vector[i].iov_len);
399                         if (rc < 0) {
400                                 return gnutls_error_to_ntstatus(rc,
401                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
402                         }
403                 }
404                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
405                 memcpy(signature, digest, 16);
406                 ZERO_ARRAY(digest);
407                 return NT_STATUS_OK;
408         }
409
410         return NT_STATUS_HMAC_NOT_SUPPORTED;
411 }
412
413 NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
414                                struct iovec *vector,
415                                int count)
416 {
417         uint16_t sign_algo_id;
418         uint8_t *hdr;
419         uint64_t session_id;
420         uint8_t res[16];
421         NTSTATUS status;
422
423         /*
424          * We expect
425          * - SMB2 HDR
426          * - SMB2 BODY FIXED
427          * - (optional) SMB2 BODY DYN
428          * - (optional) PADDING
429          */
430         SMB_ASSERT(count >= 2);
431         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
432         SMB_ASSERT(count <= 4);
433
434         hdr = (uint8_t *)vector[0].iov_base;
435
436         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
437         if (session_id == 0) {
438                 /*
439                  * do not sign messages with a zero session_id.
440                  * See MS-SMB2 3.2.4.1.1
441                  */
442                 return NT_STATUS_OK;
443         }
444
445         if (!smb2_signing_key_valid(signing_key)) {
446                 DBG_WARNING("No signing key for SMB2 signing\n");
447                 return NT_STATUS_ACCESS_DENIED;
448         }
449
450         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
451
452         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
453
454         sign_algo_id = signing_key->sign_algo_id;
455
456         status = smb2_signing_calc_signature(signing_key,
457                                              sign_algo_id,
458                                              vector,
459                                              count,
460                                              res);
461         if (!NT_STATUS_IS_OK(status)) {
462                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
463                         (unsigned)sign_algo_id, nt_errstr(status));
464                 return status;
465         }
466
467         DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
468                  (unsigned)sign_algo_id));
469
470         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
471
472         return NT_STATUS_OK;
473 }
474
475 NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
476                                 const struct iovec *vector,
477                                 int count)
478 {
479         uint16_t sign_algo_id;
480         const uint8_t *hdr;
481         const uint8_t *sig;
482         uint64_t session_id;
483         uint8_t res[16];
484         NTSTATUS status;
485
486         /*
487          * We expect
488          * - SMB2 HDR
489          * - SMB2 BODY FIXED
490          * - (optional) SMB2 BODY DYN
491          * - (optional) PADDING
492          */
493         SMB_ASSERT(count >= 2);
494         SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
495         SMB_ASSERT(count <= 4);
496
497         hdr = (const uint8_t *)vector[0].iov_base;
498
499         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
500         if (session_id == 0) {
501                 /*
502                  * do not sign messages with a zero session_id.
503                  * See MS-SMB2 3.2.4.1.1
504                  */
505                 return NT_STATUS_OK;
506         }
507
508         if (!smb2_signing_key_valid(signing_key)) {
509                 /* we don't have the session key yet */
510                 return NT_STATUS_OK;
511         }
512
513         sig = hdr+SMB2_HDR_SIGNATURE;
514
515         sign_algo_id = signing_key->sign_algo_id;
516
517         status = smb2_signing_calc_signature(signing_key,
518                                              sign_algo_id,
519                                              vector,
520                                              count,
521                                              res);
522         if (!NT_STATUS_IS_OK(status)) {
523                 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
524                         (unsigned)sign_algo_id, nt_errstr(status));
525                 return status;
526         }
527
528         if (memcmp_const_time(res, sig, 16) != 0) {
529                 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
530                          (unsigned)sign_algo_id));
531                 dump_data(0, sig, 16);
532                 dump_data(0, res, 16);
533                 return NT_STATUS_ACCESS_DENIED;
534         }
535
536         return NT_STATUS_OK;
537 }
538
539 NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
540                              const uint8_t *Label, size_t Label_len,
541                              const uint8_t *Context, size_t Context_len,
542                              uint8_t *KO, size_t KO_len)
543 {
544         gnutls_hmac_hd_t hmac_hnd = NULL;
545         uint8_t buf[4];
546         static const uint8_t zero = 0;
547         const size_t digest_len = gnutls_hash_get_len(GNUTLS_MAC_SHA256);
548         uint8_t digest[digest_len];
549         uint32_t i = 1;
550         uint32_t L = KO_len * 8;
551         int rc;
552
553         if (KO_len > digest_len) {
554                 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len, digest_len);
555                 return NT_STATUS_INTERNAL_ERROR;
556         }
557
558         switch (KO_len) {
559         case 16:
560         case 32:
561                 break;
562         default:
563                 DBG_ERR("KO_len[%zu] not supported\n", KO_len);
564                 return NT_STATUS_INTERNAL_ERROR;
565         }
566
567         /*
568          * a simplified version of
569          * "NIST Special Publication 800-108" section 5.1
570          * using hmac-sha256.
571          */
572         rc = gnutls_hmac_init(&hmac_hnd,
573                               GNUTLS_MAC_SHA256,
574                               KI,
575                               KI_len);
576         if (rc < 0) {
577                 return gnutls_error_to_ntstatus(rc,
578                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
579         }
580
581         RSIVAL(buf, 0, i);
582         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
583         if (rc < 0) {
584                 return gnutls_error_to_ntstatus(rc,
585                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
586         }
587         rc = gnutls_hmac(hmac_hnd, Label, Label_len);
588         if (rc < 0) {
589                 gnutls_hmac_deinit(hmac_hnd, NULL);
590                 return gnutls_error_to_ntstatus(rc,
591                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
592         }
593         rc = gnutls_hmac(hmac_hnd, &zero, 1);
594         if (rc < 0) {
595                 gnutls_hmac_deinit(hmac_hnd, NULL);
596                 return gnutls_error_to_ntstatus(rc,
597                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
598         }
599         rc = gnutls_hmac(hmac_hnd, Context, Context_len);
600         if (rc < 0) {
601                 gnutls_hmac_deinit(hmac_hnd, NULL);
602                 return gnutls_error_to_ntstatus(rc,
603                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
604         }
605         RSIVAL(buf, 0, L);
606         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
607         if (rc < 0) {
608                 gnutls_hmac_deinit(hmac_hnd, NULL);
609                 return gnutls_error_to_ntstatus(rc,
610                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
611         }
612
613         gnutls_hmac_deinit(hmac_hnd, digest);
614
615         memcpy(KO, digest, KO_len);
616
617         ZERO_ARRAY(digest);
618
619         return NT_STATUS_OK;
620 }
621
622 NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
623                                   uint16_t cipher_id,
624                                   struct iovec *vector,
625                                   int count)
626 {
627         uint8_t *tf;
628         size_t a_total;
629         ssize_t m_total;
630         uint32_t iv_size = 0;
631         uint32_t key_size = 0;
632         size_t tag_size = 0;
633         uint8_t _key[16] = {0};
634         gnutls_cipher_algorithm_t algo = 0;
635         gnutls_datum_t key;
636         gnutls_datum_t iv;
637         NTSTATUS status;
638         int rc;
639
640         if (count < 1) {
641                 return NT_STATUS_INVALID_PARAMETER;
642         }
643
644         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
645                 return NT_STATUS_INVALID_PARAMETER;
646         }
647
648         tf = (uint8_t *)vector[0].iov_base;
649
650         if (!smb2_signing_key_valid(encryption_key)) {
651                 DBG_WARNING("No encryption key for SMB2 signing\n");
652                 return NT_STATUS_ACCESS_DENIED;
653         }
654
655         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
656
657         m_total = iov_buflen(&vector[1], count-1);
658         if (m_total == -1) {
659                 return NT_STATUS_BUFFER_TOO_SMALL;
660         }
661
662         SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
663         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
664
665         switch (cipher_id) {
666         case SMB2_ENCRYPTION_AES128_CCM:
667                 algo = GNUTLS_CIPHER_AES_128_CCM;
668                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
669                 break;
670         case SMB2_ENCRYPTION_AES128_GCM:
671                 algo = GNUTLS_CIPHER_AES_128_GCM;
672                 iv_size = gnutls_cipher_get_iv_size(algo);
673                 break;
674         default:
675                 return NT_STATUS_INVALID_PARAMETER;
676         }
677
678         key_size = gnutls_cipher_get_key_size(algo);
679         tag_size = gnutls_cipher_get_tag_size(algo);
680
681         if (key_size > sizeof(_key)) {
682                 return NT_STATUS_BUFFER_TOO_SMALL;
683         }
684
685         key = (gnutls_datum_t) {
686                 .data = _key,
687                 .size = key_size,
688         };
689
690         memcpy(key.data,
691                encryption_key->blob.data,
692                MIN(encryption_key->blob.length, key.size));
693
694         iv = (gnutls_datum_t) {
695                 .data = tf + SMB2_TF_NONCE,
696                 .size = iv_size,
697         };
698
699         if (encryption_key->cipher_hnd == NULL) {
700                 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
701                                         algo,
702                                         &key);
703                 if (rc < 0) {
704                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
705                         goto out;
706                 }
707         }
708
709         memset(tf + SMB2_TF_NONCE + iv_size,
710                0,
711                16 - iv_size);
712
713 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
714         {
715                 uint8_t tag[tag_size];
716                 giovec_t auth_iov[1];
717
718                 auth_iov[0] = (giovec_t) {
719                         .iov_base = tf + SMB2_TF_NONCE,
720                         .iov_len  = a_total,
721                 };
722
723                 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
724                                                   iv.data,
725                                                   iv.size,
726                                                   auth_iov,
727                                                   1,
728                                                   &vector[1],
729                                                   count - 1,
730                                                   tag,
731                                                   &tag_size);
732                 if (rc < 0) {
733                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
734                         goto out;
735                 }
736
737                 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
738         }
739 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
740         {
741                 size_t ptext_size = m_total;
742                 uint8_t *ptext = NULL;
743                 size_t ctext_size = m_total + tag_size;
744                 uint8_t *ctext = NULL;
745                 size_t len = 0;
746                 int i;
747                 TALLOC_CTX *tmp_ctx = NULL;
748
749                 /*
750                  * If we come from python bindings, we don't have a stackframe
751                  * around, so use the NULL context.
752                  *
753                  * This is fine as we make sure we free the memory.
754                  */
755                 if (talloc_stackframe_exists()) {
756                         tmp_ctx = talloc_tos();
757                 }
758
759                 ptext = talloc_size(tmp_ctx, ptext_size);
760                 if (ptext == NULL) {
761                         status = NT_STATUS_NO_MEMORY;
762                         goto out;
763                 }
764
765                 ctext = talloc_size(tmp_ctx, ctext_size);
766                 if (ctext == NULL) {
767                         TALLOC_FREE(ptext);
768                         status = NT_STATUS_NO_MEMORY;
769                         goto out;
770                 }
771
772                 for (i = 1; i < count; i++) {
773                         memcpy(ptext + len,
774                                vector[i].iov_base,
775                                vector[i].iov_len);
776
777                         len += vector[i].iov_len;
778                         if (len > ptext_size) {
779                                 TALLOC_FREE(ptext);
780                                 TALLOC_FREE(ctext);
781                                 status = NT_STATUS_INTERNAL_ERROR;
782                                 goto out;
783                         }
784                 }
785
786                 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
787                                                 iv.data,
788                                                 iv.size,
789                                                 tf + SMB2_TF_NONCE,
790                                                 a_total,
791                                                 tag_size,
792                                                 ptext,
793                                                 ptext_size,
794                                                 ctext,
795                                                 &ctext_size);
796                 if (rc < 0 || ctext_size != m_total + tag_size) {
797                         TALLOC_FREE(ptext);
798                         TALLOC_FREE(ctext);
799                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
800                         goto out;
801                 }
802
803                 len = 0;
804                 for (i = 1; i < count; i++) {
805                         memcpy(vector[i].iov_base,
806                                ctext + len,
807                                vector[i].iov_len);
808
809                         len += vector[i].iov_len;
810                 }
811
812                 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
813
814                 TALLOC_FREE(ptext);
815                 TALLOC_FREE(ctext);
816         }
817 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
818
819         DBG_INFO("Encrypted SMB2 message\n");
820
821         status = NT_STATUS_OK;
822 out:
823         ZERO_ARRAY(_key);
824
825         return status;
826 }
827
828 NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
829                                   uint16_t cipher_id,
830                                   struct iovec *vector,
831                                   int count)
832 {
833         uint8_t *tf;
834         uint16_t flags;
835         size_t a_total;
836         ssize_t m_total;
837         uint32_t msg_size = 0;
838         uint32_t iv_size = 0;
839         uint32_t key_size = 0;
840         size_t tag_size = 0;
841         uint8_t _key[16] = {0};
842         gnutls_cipher_algorithm_t algo = 0;
843         gnutls_datum_t key;
844         gnutls_datum_t iv;
845         NTSTATUS status;
846         int rc;
847
848         if (count < 1) {
849                 return NT_STATUS_INVALID_PARAMETER;
850         }
851
852         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
853                 return NT_STATUS_INVALID_PARAMETER;
854         }
855
856         tf = (uint8_t *)vector[0].iov_base;
857
858         if (!smb2_signing_key_valid(decryption_key)) {
859                 DBG_WARNING("No decryption key for SMB2 signing\n");
860                 return NT_STATUS_ACCESS_DENIED;
861         }
862
863         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
864
865         m_total = iov_buflen(&vector[1], count-1);
866         if (m_total == -1) {
867                 return NT_STATUS_BUFFER_TOO_SMALL;
868         }
869
870         flags = SVAL(tf, SMB2_TF_FLAGS);
871         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
872
873         if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
874                 return NT_STATUS_ACCESS_DENIED;
875         }
876
877         if (msg_size != m_total) {
878                 return NT_STATUS_INTERNAL_ERROR;
879         }
880
881         switch (cipher_id) {
882         case SMB2_ENCRYPTION_AES128_CCM:
883                 algo = GNUTLS_CIPHER_AES_128_CCM;
884                 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
885                 break;
886         case SMB2_ENCRYPTION_AES128_GCM:
887                 algo = GNUTLS_CIPHER_AES_128_GCM;
888                 iv_size = gnutls_cipher_get_iv_size(algo);
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 > sizeof(_key)) {
898                 return NT_STATUS_BUFFER_TOO_SMALL;
899         }
900
901         key = (gnutls_datum_t) {
902                 .data = _key,
903                 .size = key_size,
904         };
905
906         memcpy(key.data,
907                decryption_key->blob.data,
908                MIN(decryption_key->blob.length, key.size));
909
910         iv = (gnutls_datum_t) {
911                 .data = tf + SMB2_TF_NONCE,
912                 .size = iv_size,
913         };
914
915         if (decryption_key->cipher_hnd == NULL) {
916                 rc = gnutls_aead_cipher_init(&decryption_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 /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
926 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
927         {
928                 giovec_t auth_iov[1];
929
930                 auth_iov[0] = (giovec_t) {
931                         .iov_base = tf + SMB2_TF_NONCE,
932                         .iov_len  = a_total,
933                 };
934
935                 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
936                                                   iv.data,
937                                                   iv.size,
938                                                   auth_iov,
939                                                   1,
940                                                   &vector[1],
941                                                   count - 1,
942                                                   tf + SMB2_TF_SIGNATURE,
943                                                   tag_size);
944                 if (rc < 0) {
945                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
946                         goto out;
947                 }
948         }
949 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
950         {
951                 size_t ctext_size = m_total + tag_size;
952                 uint8_t *ctext = NULL;
953                 size_t ptext_size = m_total;
954                 uint8_t *ptext = NULL;
955                 size_t len = 0;
956                 int i;
957                 TALLOC_CTX *tmp_ctx = NULL;
958
959                 /*
960                  * If we come from python bindings, we don't have a stackframe
961                  * around, so use the NULL context.
962                  *
963                  * This is fine as we make sure we free the memory.
964                  */
965                 if (talloc_stackframe_exists()) {
966                         tmp_ctx = talloc_tos();
967                 }
968
969                 /* GnuTLS doesn't have a iovec API for decryption yet */
970
971                 ptext = talloc_size(tmp_ctx, ptext_size);
972                 if (ptext == NULL) {
973                         status = NT_STATUS_NO_MEMORY;
974                         goto out;
975                 }
976
977                 ctext = talloc_size(tmp_ctx, ctext_size);
978                 if (ctext == NULL) {
979                         TALLOC_FREE(ptext);
980                         status = NT_STATUS_NO_MEMORY;
981                         goto out;
982                 }
983
984
985                 for (i = 1; i < count; i++) {
986                         memcpy(ctext + len,
987                                vector[i].iov_base,
988                                vector[i].iov_len);
989
990                         len += vector[i].iov_len;
991                 }
992                 if (len != m_total) {
993                         TALLOC_FREE(ptext);
994                         TALLOC_FREE(ctext);
995                         status = NT_STATUS_INTERNAL_ERROR;
996                         goto out;
997                 }
998
999                 memcpy(ctext + len,
1000                        tf + SMB2_TF_SIGNATURE,
1001                        tag_size);
1002
1003                 /* This function will verify the tag */
1004                 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
1005                                                 iv.data,
1006                                                 iv.size,
1007                                                 tf + SMB2_TF_NONCE,
1008                                                 a_total,
1009                                                 tag_size,
1010                                                 ctext,
1011                                                 ctext_size,
1012                                                 ptext,
1013                                                 &ptext_size);
1014                 if (rc < 0 || ptext_size != m_total) {
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                         memcpy(vector[i].iov_base,
1024                                ptext + len,
1025                                vector[i].iov_len);
1026
1027                         len += vector[i].iov_len;
1028                 }
1029
1030                 TALLOC_FREE(ptext);
1031                 TALLOC_FREE(ctext);
1032         }
1033 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
1034
1035         DBG_INFO("Decrypted SMB2 message\n");
1036
1037         status = NT_STATUS_OK;
1038 out:
1039         ZERO_ARRAY(_key);
1040
1041         return status;
1042 }