libcli/smb: add aes-256-{gcm,ccm} support to smb2_signing_[en|de]crypt_pdu()
[Samba.git] / libcli / smb / smb2_signing.c
bloba372d37e66d17fece69131a1c91d171d590aaab8
1 /*
2 Unix SMB/CIFS implementation.
3 SMB2 signing
5 Copyright (C) Stefan Metzmacher 2009
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.
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.
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/>.
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"
30 #ifndef HAVE_GNUTLS_AES_CMAC
31 #include "lib/crypto/aes.h"
32 #include "lib/crypto/aes_cmac_128.h"
33 #endif
35 #include "lib/crypto/gnutls_helpers.h"
37 void smb2_signing_derivations_fill_const_stack(struct smb2_signing_derivations *ds,
38 enum protocol_types protocol,
39 const DATA_BLOB preauth_hash)
41 *ds = (struct smb2_signing_derivations) { .signing = NULL, };
43 if (protocol >= PROTOCOL_SMB3_11) {
44 struct smb2_signing_derivation *d = NULL;
46 SMB_ASSERT(preauth_hash.length != 0);
48 d = &ds->__signing;
49 ds->signing = d;
50 d->label = data_blob_string_const_null("SMBSigningKey");
51 d->context = preauth_hash;
53 d = &ds->__cipher_c2s;
54 ds->cipher_c2s = d;
55 d->label = data_blob_string_const_null("SMBC2SCipherKey");
56 d->context = preauth_hash;
58 d = &ds->__cipher_s2c;
59 ds->cipher_s2c = d;
60 d->label = data_blob_string_const_null("SMBS2CCipherKey");
61 d->context = preauth_hash;
63 d = &ds->__application;
64 ds->application = d;
65 d->label = data_blob_string_const_null("SMBAppKey");
66 d->context = preauth_hash;
68 } else if (protocol >= PROTOCOL_SMB3_00) {
69 struct smb2_signing_derivation *d = NULL;
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");
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 ");
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");
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");
93 static int smb2_signing_key_destructor(struct smb2_signing_key *key)
95 if (key->hmac_hnd != NULL) {
96 gnutls_hmac_deinit(key->hmac_hnd, NULL);
97 key->hmac_hnd = NULL;
100 if (key->cipher_hnd != NULL) {
101 gnutls_aead_cipher_deinit(key->cipher_hnd);
102 key->cipher_hnd = NULL;
105 return 0;
108 NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
109 const struct smb2_signing_key *src,
110 struct smb2_signing_key **_dst)
112 struct smb2_signing_key *dst = NULL;
114 dst = talloc_zero(mem_ctx, struct smb2_signing_key);
115 if (dst == NULL) {
116 return NT_STATUS_NO_MEMORY;
118 talloc_set_destructor(dst, smb2_signing_key_destructor);
120 dst->sign_algo_id = src->sign_algo_id;
121 dst->cipher_algo_id = src->cipher_algo_id;
123 if (src->blob.length == 0) {
124 *_dst = dst;
125 return NT_STATUS_OK;
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;
133 talloc_keep_secret(dst->blob.data);
134 memcpy(dst->blob.data, src->blob.data, dst->blob.length);
136 *_dst = dst;
137 return NT_STATUS_OK;
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)
147 struct smb2_signing_key *key = NULL;
148 size_t in_key_length = 16;
149 size_t out_key_length = 16;
150 NTSTATUS status;
152 if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
153 SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
155 if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
156 SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
159 key = talloc_zero(mem_ctx, struct smb2_signing_key);
160 if (key == NULL) {
161 return NT_STATUS_NO_MEMORY;
163 talloc_set_destructor(key, smb2_signing_key_destructor);
165 key->sign_algo_id = sign_algo_id;
166 key->cipher_algo_id = cipher_algo_id;
168 if (master_key == NULL) {
169 SMB_ASSERT(d == NULL);
171 *_key = key;
172 return NT_STATUS_OK;
176 * Per default use the full key.
178 in_key_length = out_key_length = master_key->length;
179 switch (sign_algo_id) {
180 case SMB2_SIGNING_INVALID_ALGO:
182 * This means we're processing cipher_algo_id below
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:
191 * signing keys are padded or truncated to
192 * 16 bytes.
194 * Even with master_key->length = 0,
195 * we need to use 16 zeros.
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;
203 switch (cipher_algo_id) {
204 case SMB2_ENCRYPTION_INVALID_ALGO:
206 * This means we're processing sign_algo_id above
208 break;
209 case SMB2_ENCRYPTION_NONE:
211 * No encryption negotiated.
213 break;
214 case SMB2_ENCRYPTION_AES128_CCM:
215 case SMB2_ENCRYPTION_AES128_GCM:
217 * encryption keys are padded or truncated to
218 * 16 bytes.
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;
225 in_key_length = out_key_length = 16;
226 break;
227 case SMB2_ENCRYPTION_AES256_CCM:
228 case SMB2_ENCRYPTION_AES256_GCM:
230 * AES256 uses the available input and
231 * generated a 32 byte encryption key.
233 if (master_key->length == 0) {
234 DBG_ERR("cipher_algo_id[%u] without key\n",
235 cipher_algo_id);
236 return NT_STATUS_NO_USER_SESSION_KEY;
238 out_key_length = 32;
239 break;
240 default:
241 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id);
242 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG;
245 if (out_key_length == 0) {
246 *_key = key;
247 return NT_STATUS_OK;
250 key->blob = data_blob_talloc_zero(key, out_key_length);
251 if (key->blob.length == 0) {
252 TALLOC_FREE(key);
253 return NT_STATUS_NO_MEMORY;
255 talloc_keep_secret(key->blob.data);
256 memcpy(key->blob.data,
257 master_key->data,
258 MIN(key->blob.length, master_key->length));
260 if (d == NULL) {
261 *_key = key;
262 return NT_STATUS_OK;
265 status = smb2_key_derivation(key->blob.data, in_key_length,
266 d->label.data, d->label.length,
267 d->context.data, d->context.length,
268 key->blob.data, out_key_length);
269 if (!NT_STATUS_IS_OK(status)) {
270 TALLOC_FREE(key);
271 return status;
274 *_key = key;
275 return NT_STATUS_OK;
278 NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
279 uint16_t sign_algo_id,
280 const DATA_BLOB *master_key,
281 const struct smb2_signing_derivation *d,
282 struct smb2_signing_key **_key)
284 return smb2_signing_key_create(mem_ctx,
285 sign_algo_id,
286 SMB2_ENCRYPTION_INVALID_ALGO,
287 master_key,
289 _key);
292 NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
293 uint16_t cipher_algo_id,
294 const DATA_BLOB *master_key,
295 const struct smb2_signing_derivation *d,
296 struct smb2_signing_key **_key)
298 return smb2_signing_key_create(mem_ctx,
299 SMB2_SIGNING_INVALID_ALGO,
300 cipher_algo_id,
301 master_key,
303 _key);
306 bool smb2_signing_key_valid(const struct smb2_signing_key *key)
308 if (key == NULL) {
309 return false;
312 if (key->blob.length == 0 || key->blob.data == NULL) {
313 return false;
316 return true;
319 static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
320 uint16_t sign_algo_id,
321 const struct iovec *vector,
322 int count,
323 uint8_t signature[16])
325 const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
326 static const uint8_t zero_sig[16] = { 0, };
327 gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
328 int i;
331 * We expect
332 * - SMB2 HDR
333 * - SMB2 BODY FIXED
334 * - (optional) SMB2 BODY DYN
335 * - (optional) PADDING
337 SMB_ASSERT(count >= 2);
338 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
339 SMB_ASSERT(count <= 4);
341 switch (sign_algo_id) {
342 case SMB2_SIGNING_AES128_CMAC:
343 #ifdef HAVE_GNUTLS_AES_CMAC
344 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
345 break;
346 #else /* NOT HAVE_GNUTLS_AES_CMAC */
348 struct aes_cmac_128_context ctx;
349 uint8_t key[AES_BLOCK_SIZE] = {0};
351 memcpy(key,
352 signing_key->blob.data,
353 MIN(signing_key->blob.length, 16));
355 aes_cmac_128_init(&ctx, key);
356 aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
357 aes_cmac_128_update(&ctx, zero_sig, 16);
358 for (i=1; i < count; i++) {
359 aes_cmac_128_update(&ctx,
360 (const uint8_t *)vector[i].iov_base,
361 vector[i].iov_len);
363 aes_cmac_128_final(&ctx, signature);
365 ZERO_ARRAY(key);
367 return NT_STATUS_OK;
368 } break;
369 #endif
370 case SMB2_SIGNING_HMAC_SHA256:
371 hmac_algo = GNUTLS_MAC_SHA256;
372 break;
374 default:
375 return NT_STATUS_HMAC_NOT_SUPPORTED;
378 if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
379 uint8_t digest[gnutls_hash_get_len(hmac_algo)];
380 gnutls_datum_t key = {
381 .data = signing_key->blob.data,
382 .size = MIN(signing_key->blob.length, 16),
384 int rc;
386 if (signing_key->hmac_hnd == NULL) {
387 rc = gnutls_hmac_init(&signing_key->hmac_hnd,
388 hmac_algo,
389 key.data,
390 key.size);
391 if (rc < 0) {
392 return gnutls_error_to_ntstatus(rc,
393 NT_STATUS_HMAC_NOT_SUPPORTED);
397 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
398 if (rc < 0) {
399 return gnutls_error_to_ntstatus(rc,
400 NT_STATUS_HMAC_NOT_SUPPORTED);
402 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
403 if (rc < 0) {
404 return gnutls_error_to_ntstatus(rc,
405 NT_STATUS_HMAC_NOT_SUPPORTED);
408 for (i = 1; i < count; i++) {
409 rc = gnutls_hmac(signing_key->hmac_hnd,
410 vector[i].iov_base,
411 vector[i].iov_len);
412 if (rc < 0) {
413 return gnutls_error_to_ntstatus(rc,
414 NT_STATUS_HMAC_NOT_SUPPORTED);
417 gnutls_hmac_output(signing_key->hmac_hnd, digest);
418 memcpy(signature, digest, 16);
419 ZERO_ARRAY(digest);
420 return NT_STATUS_OK;
423 return NT_STATUS_HMAC_NOT_SUPPORTED;
426 NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
427 struct iovec *vector,
428 int count)
430 uint16_t sign_algo_id;
431 uint8_t *hdr;
432 uint64_t session_id;
433 uint8_t res[16];
434 NTSTATUS status;
437 * We expect
438 * - SMB2 HDR
439 * - SMB2 BODY FIXED
440 * - (optional) SMB2 BODY DYN
441 * - (optional) PADDING
443 SMB_ASSERT(count >= 2);
444 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
445 SMB_ASSERT(count <= 4);
447 hdr = (uint8_t *)vector[0].iov_base;
449 session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
450 if (session_id == 0) {
452 * do not sign messages with a zero session_id.
453 * See MS-SMB2 3.2.4.1.1
455 return NT_STATUS_OK;
458 if (!smb2_signing_key_valid(signing_key)) {
459 DBG_WARNING("No signing key for SMB2 signing\n");
460 return NT_STATUS_ACCESS_DENIED;
463 memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
465 SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
467 sign_algo_id = signing_key->sign_algo_id;
469 status = smb2_signing_calc_signature(signing_key,
470 sign_algo_id,
471 vector,
472 count,
473 res);
474 if (!NT_STATUS_IS_OK(status)) {
475 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
476 (unsigned)sign_algo_id, nt_errstr(status));
477 return status;
480 DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
481 (unsigned)sign_algo_id));
483 memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
485 return NT_STATUS_OK;
488 NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
489 const struct iovec *vector,
490 int count)
492 uint16_t sign_algo_id;
493 const uint8_t *hdr;
494 const uint8_t *sig;
495 uint64_t session_id;
496 uint8_t res[16];
497 NTSTATUS status;
500 * We expect
501 * - SMB2 HDR
502 * - SMB2 BODY FIXED
503 * - (optional) SMB2 BODY DYN
504 * - (optional) PADDING
506 SMB_ASSERT(count >= 2);
507 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
508 SMB_ASSERT(count <= 4);
510 hdr = (const uint8_t *)vector[0].iov_base;
512 session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
513 if (session_id == 0) {
515 * do not sign messages with a zero session_id.
516 * See MS-SMB2 3.2.4.1.1
518 return NT_STATUS_OK;
521 if (!smb2_signing_key_valid(signing_key)) {
522 /* we don't have the session key yet */
523 return NT_STATUS_OK;
526 sig = hdr+SMB2_HDR_SIGNATURE;
528 sign_algo_id = signing_key->sign_algo_id;
530 status = smb2_signing_calc_signature(signing_key,
531 sign_algo_id,
532 vector,
533 count,
534 res);
535 if (!NT_STATUS_IS_OK(status)) {
536 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
537 (unsigned)sign_algo_id, nt_errstr(status));
538 return status;
541 if (memcmp_const_time(res, sig, 16) != 0) {
542 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
543 (unsigned)sign_algo_id));
544 dump_data(0, sig, 16);
545 dump_data(0, res, 16);
546 return NT_STATUS_ACCESS_DENIED;
549 return NT_STATUS_OK;
552 NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
553 const uint8_t *Label, size_t Label_len,
554 const uint8_t *Context, size_t Context_len,
555 uint8_t *KO, size_t KO_len)
557 gnutls_hmac_hd_t hmac_hnd = NULL;
558 uint8_t buf[4];
559 static const uint8_t zero = 0;
560 const size_t digest_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
561 uint8_t digest[digest_len];
562 uint32_t i = 1;
563 uint32_t L = KO_len * 8;
564 int rc;
566 if (KO_len > digest_len) {
567 DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len, digest_len);
568 return NT_STATUS_INTERNAL_ERROR;
571 switch (KO_len) {
572 case 16:
573 case 32:
574 break;
575 default:
576 DBG_ERR("KO_len[%zu] not supported\n", KO_len);
577 return NT_STATUS_INTERNAL_ERROR;
581 * a simplified version of
582 * "NIST Special Publication 800-108" section 5.1
583 * using hmac-sha256.
585 rc = gnutls_hmac_init(&hmac_hnd,
586 GNUTLS_MAC_SHA256,
588 KI_len);
589 if (rc < 0) {
590 return gnutls_error_to_ntstatus(rc,
591 NT_STATUS_HMAC_NOT_SUPPORTED);
594 RSIVAL(buf, 0, i);
595 rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
596 if (rc < 0) {
597 return gnutls_error_to_ntstatus(rc,
598 NT_STATUS_HMAC_NOT_SUPPORTED);
600 rc = gnutls_hmac(hmac_hnd, Label, Label_len);
601 if (rc < 0) {
602 gnutls_hmac_deinit(hmac_hnd, NULL);
603 return gnutls_error_to_ntstatus(rc,
604 NT_STATUS_HMAC_NOT_SUPPORTED);
606 rc = gnutls_hmac(hmac_hnd, &zero, 1);
607 if (rc < 0) {
608 gnutls_hmac_deinit(hmac_hnd, NULL);
609 return gnutls_error_to_ntstatus(rc,
610 NT_STATUS_HMAC_NOT_SUPPORTED);
612 rc = gnutls_hmac(hmac_hnd, Context, Context_len);
613 if (rc < 0) {
614 gnutls_hmac_deinit(hmac_hnd, NULL);
615 return gnutls_error_to_ntstatus(rc,
616 NT_STATUS_HMAC_NOT_SUPPORTED);
618 RSIVAL(buf, 0, L);
619 rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
620 if (rc < 0) {
621 gnutls_hmac_deinit(hmac_hnd, NULL);
622 return gnutls_error_to_ntstatus(rc,
623 NT_STATUS_HMAC_NOT_SUPPORTED);
626 gnutls_hmac_deinit(hmac_hnd, digest);
628 memcpy(KO, digest, KO_len);
630 ZERO_ARRAY(digest);
632 return NT_STATUS_OK;
635 NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
636 struct iovec *vector,
637 int count)
639 uint16_t cipher_id;
640 uint8_t *tf;
641 size_t a_total;
642 ssize_t m_total;
643 uint32_t iv_size = 0;
644 uint32_t key_size = 0;
645 size_t tag_size = 0;
646 gnutls_cipher_algorithm_t algo = 0;
647 gnutls_datum_t key;
648 gnutls_datum_t iv;
649 NTSTATUS status;
650 int rc;
652 if (count < 1) {
653 return NT_STATUS_INVALID_PARAMETER;
656 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
657 return NT_STATUS_INVALID_PARAMETER;
660 tf = (uint8_t *)vector[0].iov_base;
662 if (!smb2_signing_key_valid(encryption_key)) {
663 DBG_WARNING("No encryption key for SMB2 signing\n");
664 return NT_STATUS_ACCESS_DENIED;
666 cipher_id = encryption_key->cipher_algo_id;
668 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
670 m_total = iov_buflen(&vector[1], count-1);
671 if (m_total == -1) {
672 return NT_STATUS_BUFFER_TOO_SMALL;
675 SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
676 SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
678 switch (cipher_id) {
679 case SMB2_ENCRYPTION_AES128_CCM:
680 algo = GNUTLS_CIPHER_AES_128_CCM;
681 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
682 break;
683 case SMB2_ENCRYPTION_AES128_GCM:
684 algo = GNUTLS_CIPHER_AES_128_GCM;
685 iv_size = gnutls_cipher_get_iv_size(algo);
686 break;
687 case SMB2_ENCRYPTION_AES256_CCM:
688 algo = GNUTLS_CIPHER_AES_256_CCM;
689 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
690 break;
691 case SMB2_ENCRYPTION_AES256_GCM:
692 algo = GNUTLS_CIPHER_AES_256_GCM;
693 iv_size = gnutls_cipher_get_iv_size(algo);
694 break;
695 default:
696 return NT_STATUS_INVALID_PARAMETER;
699 key_size = gnutls_cipher_get_key_size(algo);
700 tag_size = gnutls_cipher_get_tag_size(algo);
702 if (key_size != encryption_key->blob.length) {
703 return NT_STATUS_INTERNAL_ERROR;
706 if (tag_size != 16) {
707 return NT_STATUS_INTERNAL_ERROR;
710 key = (gnutls_datum_t) {
711 .data = encryption_key->blob.data,
712 .size = key_size,
715 iv = (gnutls_datum_t) {
716 .data = tf + SMB2_TF_NONCE,
717 .size = iv_size,
720 if (encryption_key->cipher_hnd == NULL) {
721 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
722 algo,
723 &key);
724 if (rc < 0) {
725 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
726 goto out;
730 memset(tf + SMB2_TF_NONCE + iv_size,
732 16 - iv_size);
734 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
736 uint8_t tag[tag_size];
737 giovec_t auth_iov[1];
739 auth_iov[0] = (giovec_t) {
740 .iov_base = tf + SMB2_TF_NONCE,
741 .iov_len = a_total,
744 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
745 iv.data,
746 iv.size,
747 auth_iov,
749 &vector[1],
750 count - 1,
751 tag,
752 &tag_size);
753 if (rc < 0) {
754 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
755 goto out;
758 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
760 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
762 size_t ptext_size = m_total;
763 uint8_t *ptext = NULL;
764 size_t ctext_size = m_total + tag_size;
765 uint8_t *ctext = NULL;
766 size_t len = 0;
767 int i;
768 TALLOC_CTX *tmp_ctx = NULL;
771 * If we come from python bindings, we don't have a stackframe
772 * around, so use the NULL context.
774 * This is fine as we make sure we free the memory.
776 if (talloc_stackframe_exists()) {
777 tmp_ctx = talloc_tos();
780 ptext = talloc_size(tmp_ctx, ptext_size);
781 if (ptext == NULL) {
782 status = NT_STATUS_NO_MEMORY;
783 goto out;
786 ctext = talloc_size(tmp_ctx, ctext_size);
787 if (ctext == NULL) {
788 TALLOC_FREE(ptext);
789 status = NT_STATUS_NO_MEMORY;
790 goto out;
793 for (i = 1; i < count; i++) {
794 memcpy(ptext + len,
795 vector[i].iov_base,
796 vector[i].iov_len);
798 len += vector[i].iov_len;
799 if (len > ptext_size) {
800 TALLOC_FREE(ptext);
801 TALLOC_FREE(ctext);
802 status = NT_STATUS_INTERNAL_ERROR;
803 goto out;
807 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
808 iv.data,
809 iv.size,
810 tf + SMB2_TF_NONCE,
811 a_total,
812 tag_size,
813 ptext,
814 ptext_size,
815 ctext,
816 &ctext_size);
817 if (rc < 0 || ctext_size != m_total + tag_size) {
818 TALLOC_FREE(ptext);
819 TALLOC_FREE(ctext);
820 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
821 goto out;
824 len = 0;
825 for (i = 1; i < count; i++) {
826 memcpy(vector[i].iov_base,
827 ctext + len,
828 vector[i].iov_len);
830 len += vector[i].iov_len;
833 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
835 TALLOC_FREE(ptext);
836 TALLOC_FREE(ctext);
838 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
840 DBG_INFO("Encrypted SMB2 message\n");
842 status = NT_STATUS_OK;
843 out:
844 return status;
847 NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
848 struct iovec *vector,
849 int count)
851 uint16_t cipher_id;
852 uint8_t *tf;
853 uint16_t flags;
854 size_t a_total;
855 ssize_t m_total;
856 uint32_t msg_size = 0;
857 uint32_t iv_size = 0;
858 uint32_t key_size = 0;
859 size_t tag_size = 0;
860 gnutls_cipher_algorithm_t algo = 0;
861 gnutls_datum_t key;
862 gnutls_datum_t iv;
863 NTSTATUS status;
864 int rc;
866 if (count < 1) {
867 return NT_STATUS_INVALID_PARAMETER;
870 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
871 return NT_STATUS_INVALID_PARAMETER;
874 tf = (uint8_t *)vector[0].iov_base;
876 if (!smb2_signing_key_valid(decryption_key)) {
877 DBG_WARNING("No decryption key for SMB2 signing\n");
878 return NT_STATUS_ACCESS_DENIED;
880 cipher_id = decryption_key->cipher_algo_id;
882 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
884 m_total = iov_buflen(&vector[1], count-1);
885 if (m_total == -1) {
886 return NT_STATUS_BUFFER_TOO_SMALL;
889 flags = SVAL(tf, SMB2_TF_FLAGS);
890 msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
892 if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
893 return NT_STATUS_ACCESS_DENIED;
896 if (msg_size != m_total) {
897 return NT_STATUS_INTERNAL_ERROR;
900 switch (cipher_id) {
901 case SMB2_ENCRYPTION_AES128_CCM:
902 algo = GNUTLS_CIPHER_AES_128_CCM;
903 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
904 break;
905 case SMB2_ENCRYPTION_AES128_GCM:
906 algo = GNUTLS_CIPHER_AES_128_GCM;
907 iv_size = gnutls_cipher_get_iv_size(algo);
908 break;
909 case SMB2_ENCRYPTION_AES256_CCM:
910 algo = GNUTLS_CIPHER_AES_256_CCM;
911 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
912 break;
913 case SMB2_ENCRYPTION_AES256_GCM:
914 algo = GNUTLS_CIPHER_AES_256_GCM;
915 iv_size = gnutls_cipher_get_iv_size(algo);
916 break;
917 default:
918 return NT_STATUS_INVALID_PARAMETER;
921 key_size = gnutls_cipher_get_key_size(algo);
922 tag_size = gnutls_cipher_get_tag_size(algo);
924 if (key_size != decryption_key->blob.length) {
925 return NT_STATUS_INTERNAL_ERROR;
928 if (tag_size != 16) {
929 return NT_STATUS_INTERNAL_ERROR;
932 key = (gnutls_datum_t) {
933 .data = decryption_key->blob.data,
934 .size = key_size,
937 iv = (gnutls_datum_t) {
938 .data = tf + SMB2_TF_NONCE,
939 .size = iv_size,
942 if (decryption_key->cipher_hnd == NULL) {
943 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
944 algo,
945 &key);
946 if (rc < 0) {
947 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
948 goto out;
952 /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
953 #if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2)
955 giovec_t auth_iov[1];
957 auth_iov[0] = (giovec_t) {
958 .iov_base = tf + SMB2_TF_NONCE,
959 .iov_len = a_total,
962 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
963 iv.data,
964 iv.size,
965 auth_iov,
967 &vector[1],
968 count - 1,
969 tf + SMB2_TF_SIGNATURE,
970 tag_size);
971 if (rc < 0) {
972 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
973 goto out;
976 #else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
978 size_t ctext_size = m_total + tag_size;
979 uint8_t *ctext = NULL;
980 size_t ptext_size = m_total;
981 uint8_t *ptext = NULL;
982 size_t len = 0;
983 int i;
984 TALLOC_CTX *tmp_ctx = NULL;
987 * If we come from python bindings, we don't have a stackframe
988 * around, so use the NULL context.
990 * This is fine as we make sure we free the memory.
992 if (talloc_stackframe_exists()) {
993 tmp_ctx = talloc_tos();
996 /* GnuTLS doesn't have a iovec API for decryption yet */
998 ptext = talloc_size(tmp_ctx, ptext_size);
999 if (ptext == NULL) {
1000 status = NT_STATUS_NO_MEMORY;
1001 goto out;
1004 ctext = talloc_size(tmp_ctx, ctext_size);
1005 if (ctext == NULL) {
1006 TALLOC_FREE(ptext);
1007 status = NT_STATUS_NO_MEMORY;
1008 goto out;
1012 for (i = 1; i < count; i++) {
1013 memcpy(ctext + len,
1014 vector[i].iov_base,
1015 vector[i].iov_len);
1017 len += vector[i].iov_len;
1019 if (len != m_total) {
1020 TALLOC_FREE(ptext);
1021 TALLOC_FREE(ctext);
1022 status = NT_STATUS_INTERNAL_ERROR;
1023 goto out;
1026 memcpy(ctext + len,
1027 tf + SMB2_TF_SIGNATURE,
1028 tag_size);
1030 /* This function will verify the tag */
1031 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
1032 iv.data,
1033 iv.size,
1034 tf + SMB2_TF_NONCE,
1035 a_total,
1036 tag_size,
1037 ctext,
1038 ctext_size,
1039 ptext,
1040 &ptext_size);
1041 if (rc < 0 || ptext_size != m_total) {
1042 TALLOC_FREE(ptext);
1043 TALLOC_FREE(ctext);
1044 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1045 goto out;
1048 len = 0;
1049 for (i = 1; i < count; i++) {
1050 memcpy(vector[i].iov_base,
1051 ptext + len,
1052 vector[i].iov_len);
1054 len += vector[i].iov_len;
1057 TALLOC_FREE(ptext);
1058 TALLOC_FREE(ctext);
1060 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
1062 DBG_INFO("Decrypted SMB2 message\n");
1064 status = NT_STATUS_OK;
1065 out:
1066 return status;