netcmd:domain:policy: Fix missing conversion from tgt_lifetime minutes to 10^(-7...
[Samba.git] / libcli / smb / smb2_signing.c
blob94ff51f2e931d583a76e2114cdcbf7da12c5e976
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 #include "lib/crypto/gnutls_helpers.h"
32 void smb2_signing_derivations_fill_const_stack(struct smb2_signing_derivations *ds,
33 enum protocol_types protocol,
34 const DATA_BLOB preauth_hash)
36 *ds = (struct smb2_signing_derivations) { .signing = NULL, };
38 if (protocol >= PROTOCOL_SMB3_11) {
39 struct smb2_signing_derivation *d = NULL;
41 SMB_ASSERT(preauth_hash.length != 0);
43 d = &ds->__signing;
44 ds->signing = d;
45 d->label = data_blob_string_const_null("SMBSigningKey");
46 d->context = preauth_hash;
48 d = &ds->__cipher_c2s;
49 ds->cipher_c2s = d;
50 d->label = data_blob_string_const_null("SMBC2SCipherKey");
51 d->context = preauth_hash;
53 d = &ds->__cipher_s2c;
54 ds->cipher_s2c = d;
55 d->label = data_blob_string_const_null("SMBS2CCipherKey");
56 d->context = preauth_hash;
58 d = &ds->__application;
59 ds->application = d;
60 d->label = data_blob_string_const_null("SMBAppKey");
61 d->context = preauth_hash;
63 } else if (protocol >= PROTOCOL_SMB3_00) {
64 struct smb2_signing_derivation *d = NULL;
66 d = &ds->__signing;
67 ds->signing = d;
68 d->label = data_blob_string_const_null("SMB2AESCMAC");
69 d->context = data_blob_string_const_null("SmbSign");
71 d = &ds->__cipher_c2s;
72 ds->cipher_c2s = d;
73 d->label = data_blob_string_const_null("SMB2AESCCM");
74 d->context = data_blob_string_const_null("ServerIn ");
76 d = &ds->__cipher_s2c;
77 ds->cipher_s2c = d;
78 d->label = data_blob_string_const_null("SMB2AESCCM");
79 d->context = data_blob_string_const_null("ServerOut");
81 d = &ds->__application;
82 ds->application = d;
83 d->label = data_blob_string_const_null("SMB2APP");
84 d->context = data_blob_string_const_null("SmbRpc");
88 static int smb2_signing_key_destructor(struct smb2_signing_key *key)
90 if (key->hmac_hnd != NULL) {
91 gnutls_hmac_deinit(key->hmac_hnd, NULL);
92 key->hmac_hnd = NULL;
95 if (key->cipher_hnd != NULL) {
96 gnutls_aead_cipher_deinit(key->cipher_hnd);
97 key->cipher_hnd = NULL;
100 return 0;
103 NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
104 const struct smb2_signing_key *src,
105 struct smb2_signing_key **_dst)
107 struct smb2_signing_key *dst = NULL;
109 dst = talloc_zero(mem_ctx, struct smb2_signing_key);
110 if (dst == NULL) {
111 return NT_STATUS_NO_MEMORY;
113 talloc_set_destructor(dst, smb2_signing_key_destructor);
115 dst->sign_algo_id = src->sign_algo_id;
116 dst->cipher_algo_id = src->cipher_algo_id;
118 if (src->blob.length == 0) {
119 *_dst = dst;
120 return NT_STATUS_OK;
123 dst->blob = data_blob_talloc_zero(dst, src->blob.length);
124 if (dst->blob.length == 0) {
125 TALLOC_FREE(dst);
126 return NT_STATUS_NO_MEMORY;
128 talloc_keep_secret(dst->blob.data);
129 memcpy(dst->blob.data, src->blob.data, dst->blob.length);
131 *_dst = dst;
132 return NT_STATUS_OK;
135 static NTSTATUS smb2_signing_key_create(TALLOC_CTX *mem_ctx,
136 uint16_t sign_algo_id,
137 uint16_t cipher_algo_id,
138 const DATA_BLOB *master_key,
139 const struct smb2_signing_derivation *d,
140 struct smb2_signing_key **_key)
142 struct smb2_signing_key *key = NULL;
143 size_t in_key_length = 16;
144 size_t out_key_length = 16;
145 NTSTATUS status;
147 if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
148 SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
150 if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
151 SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
154 key = talloc_zero(mem_ctx, struct smb2_signing_key);
155 if (key == NULL) {
156 return NT_STATUS_NO_MEMORY;
158 talloc_set_destructor(key, smb2_signing_key_destructor);
160 key->sign_algo_id = sign_algo_id;
161 key->cipher_algo_id = cipher_algo_id;
163 if (master_key == NULL) {
164 SMB_ASSERT(d == NULL);
166 *_key = key;
167 return NT_STATUS_OK;
171 * Per default use the full key.
173 in_key_length = out_key_length = master_key->length;
174 switch (sign_algo_id) {
175 case SMB2_SIGNING_INVALID_ALGO:
177 * This means we're processing cipher_algo_id below
179 break;
180 case SMB2_SIGNING_MD5_SMB1:
181 SMB_ASSERT(d == NULL);
182 break;
183 case SMB2_SIGNING_HMAC_SHA256:
184 case SMB2_SIGNING_AES128_CMAC:
185 case SMB2_SIGNING_AES128_GMAC:
187 * signing keys are padded or truncated to
188 * 16 bytes.
190 * Even with master_key->length = 0,
191 * we need to use 16 zeros.
193 in_key_length = out_key_length = 16;
194 break;
195 default:
196 DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id);
197 return NT_STATUS_HMAC_NOT_SUPPORTED;
199 switch (cipher_algo_id) {
200 case SMB2_ENCRYPTION_INVALID_ALGO:
202 * This means we're processing sign_algo_id above
204 break;
205 case SMB2_ENCRYPTION_NONE:
207 * No encryption negotiated.
209 break;
210 case SMB2_ENCRYPTION_AES128_CCM:
211 case SMB2_ENCRYPTION_AES128_GCM:
213 * encryption keys are padded or truncated to
214 * 16 bytes.
216 if (master_key->length == 0) {
217 DBG_ERR("cipher_algo_id[%u] without key\n",
218 cipher_algo_id);
219 return NT_STATUS_NO_USER_SESSION_KEY;
221 in_key_length = out_key_length = 16;
222 break;
223 case SMB2_ENCRYPTION_AES256_CCM:
224 case SMB2_ENCRYPTION_AES256_GCM:
226 * AES256 uses the available input and
227 * generated a 32 byte encryption key.
229 if (master_key->length == 0) {
230 DBG_ERR("cipher_algo_id[%u] without key\n",
231 cipher_algo_id);
232 return NT_STATUS_NO_USER_SESSION_KEY;
234 out_key_length = 32;
235 break;
236 default:
237 DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id);
238 return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG;
241 if (out_key_length == 0) {
242 *_key = key;
243 return NT_STATUS_OK;
246 key->blob = data_blob_talloc_zero(key, out_key_length);
247 if (key->blob.length == 0) {
248 TALLOC_FREE(key);
249 return NT_STATUS_NO_MEMORY;
251 talloc_keep_secret(key->blob.data);
252 memcpy(key->blob.data,
253 master_key->data,
254 MIN(key->blob.length, master_key->length));
256 if (d == NULL) {
257 *_key = key;
258 return NT_STATUS_OK;
261 status = samba_gnutls_sp800_108_derive_key(key->blob.data,
262 in_key_length,
263 NULL,
265 d->label.data,
266 d->label.length,
267 d->context.data,
268 d->context.length,
269 GNUTLS_MAC_SHA256,
270 key->blob.data,
271 out_key_length);
272 if (!NT_STATUS_IS_OK(status)) {
273 TALLOC_FREE(key);
274 return status;
277 *_key = key;
278 return NT_STATUS_OK;
281 NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
282 uint16_t sign_algo_id,
283 const DATA_BLOB *master_key,
284 const struct smb2_signing_derivation *d,
285 struct smb2_signing_key **_key)
287 return smb2_signing_key_create(mem_ctx,
288 sign_algo_id,
289 SMB2_ENCRYPTION_INVALID_ALGO,
290 master_key,
292 _key);
295 NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
296 uint16_t cipher_algo_id,
297 const DATA_BLOB *master_key,
298 const struct smb2_signing_derivation *d,
299 struct smb2_signing_key **_key)
301 return smb2_signing_key_create(mem_ctx,
302 SMB2_SIGNING_INVALID_ALGO,
303 cipher_algo_id,
304 master_key,
306 _key);
309 bool smb2_signing_key_valid(const struct smb2_signing_key *key)
311 if (key == NULL) {
312 return false;
315 if (key->blob.length == 0 || key->blob.data == NULL) {
316 return false;
319 return true;
322 static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd,
323 const uint8_t *iv, size_t iv_size,
324 const giovec_t *auth_iov, uint8_t auth_iovcnt,
325 uint8_t *tag, size_t _tag_size)
327 size_t tag_size = _tag_size;
328 int rc;
330 rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
331 iv, iv_size,
332 auth_iov, auth_iovcnt,
333 NULL, 0,
334 tag, &tag_size);
335 if (rc < 0) {
336 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
339 return NT_STATUS_OK;
342 static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
343 uint16_t sign_algo_id,
344 const struct iovec *vector,
345 int count,
346 uint8_t signature[16])
348 const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
349 uint16_t opcode;
350 uint32_t flags;
351 uint64_t msg_id;
352 static const uint8_t zero_sig[16] = { 0, };
353 gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
354 int i;
357 * We expect
358 * - SMB2 HDR
359 * - SMB2 BODY FIXED
360 * - (optional) SMB2 BODY DYN
361 * - (optional) PADDING
363 SMB_ASSERT(count >= 2);
364 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
365 SMB_ASSERT(count <= 4);
367 opcode = SVAL(hdr, SMB2_HDR_OPCODE);
368 flags = IVAL(hdr, SMB2_HDR_FLAGS);
369 if (flags & SMB2_HDR_FLAG_REDIRECT) {
370 NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
371 if (NT_STATUS_EQUAL(pdu_status, NT_STATUS_PENDING)) {
372 DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode);
373 return NT_STATUS_INTERNAL_ERROR;
375 if (opcode == SMB2_OP_CANCEL) {
376 DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
377 return NT_STATUS_INTERNAL_ERROR;
380 msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
381 if (msg_id == 0) {
382 if (opcode != SMB2_OP_CANCEL ||
383 sign_algo_id >= SMB2_SIGNING_AES128_GMAC)
385 DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
386 return NT_STATUS_INTERNAL_ERROR;
389 * Legacy algorithms allow MID 0
390 * for cancel requests
393 if (msg_id == UINT64_MAX) {
394 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
395 return NT_STATUS_INTERNAL_ERROR;
398 switch (sign_algo_id) {
399 case SMB2_SIGNING_AES128_GMAC: {
400 gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
401 uint32_t key_size = gnutls_cipher_get_key_size(algo);
402 uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
403 size_t tag_size = gnutls_cipher_get_tag_size(algo);
404 gnutls_datum_t key = {
405 .data = signing_key->blob.data,
406 .size = MIN(signing_key->blob.length, key_size),
408 uint64_t high_bits = 0;
409 uint8_t iv[AES_BLOCK_SIZE] = {0};
410 giovec_t auth_iov[count+1];
411 size_t auth_iovcnt = 0;
412 NTSTATUS status;
413 int rc;
415 high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
416 if (opcode == SMB2_OP_CANCEL) {
417 high_bits |= SMB2_HDR_FLAG_ASYNC;
419 SBVAL(iv, 0, msg_id);
420 SBVAL(iv, 8, high_bits);
422 if (signing_key->cipher_hnd == NULL) {
423 rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
424 algo,
425 &key);
426 if (rc < 0) {
427 return gnutls_error_to_ntstatus(rc,
428 NT_STATUS_HMAC_NOT_SUPPORTED);
432 SMB_ASSERT(key_size == 16);
433 SMB_ASSERT(iv_size == 12);
434 SMB_ASSERT(tag_size == 16);
436 auth_iov[auth_iovcnt++] = (giovec_t) {
437 .iov_base = discard_const_p(uint8_t, hdr),
438 .iov_len = SMB2_HDR_SIGNATURE,
440 auth_iov[auth_iovcnt++] = (giovec_t) {
441 .iov_base = discard_const_p(uint8_t, zero_sig),
442 .iov_len = 16,
444 for (i=1; i < count; i++) {
445 auth_iov[auth_iovcnt++] = (giovec_t) {
446 .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
447 .iov_len = vector[i].iov_len,
451 status = smb2_signing_gmac(signing_key->cipher_hnd,
453 iv_size,
454 auth_iov,
455 auth_iovcnt,
456 signature,
457 tag_size);
458 if (!NT_STATUS_IS_OK(status)) {
459 return status;
462 return NT_STATUS_OK;
463 } break;
465 case SMB2_SIGNING_AES128_CMAC:
466 hmac_algo = GNUTLS_MAC_AES_CMAC_128;
467 break;
468 case SMB2_SIGNING_HMAC_SHA256:
469 hmac_algo = GNUTLS_MAC_SHA256;
470 break;
472 default:
473 return NT_STATUS_HMAC_NOT_SUPPORTED;
476 if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
477 uint8_t digest[gnutls_hmac_get_len(hmac_algo)];
478 gnutls_datum_t key = {
479 .data = signing_key->blob.data,
480 .size = MIN(signing_key->blob.length, 16),
482 int rc;
484 if (signing_key->hmac_hnd == NULL) {
485 rc = gnutls_hmac_init(&signing_key->hmac_hnd,
486 hmac_algo,
487 key.data,
488 key.size);
489 if (rc < 0) {
490 return gnutls_error_to_ntstatus(rc,
491 NT_STATUS_HMAC_NOT_SUPPORTED);
495 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
496 if (rc < 0) {
497 return gnutls_error_to_ntstatus(rc,
498 NT_STATUS_HMAC_NOT_SUPPORTED);
500 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
501 if (rc < 0) {
502 return gnutls_error_to_ntstatus(rc,
503 NT_STATUS_HMAC_NOT_SUPPORTED);
506 for (i = 1; i < count; i++) {
507 rc = gnutls_hmac(signing_key->hmac_hnd,
508 vector[i].iov_base,
509 vector[i].iov_len);
510 if (rc < 0) {
511 return gnutls_error_to_ntstatus(rc,
512 NT_STATUS_HMAC_NOT_SUPPORTED);
515 gnutls_hmac_output(signing_key->hmac_hnd, digest);
516 memcpy(signature, digest, 16);
517 ZERO_ARRAY(digest);
518 return NT_STATUS_OK;
521 return NT_STATUS_HMAC_NOT_SUPPORTED;
524 NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
525 struct iovec *vector,
526 int count)
528 uint16_t sign_algo_id;
529 uint8_t *hdr;
530 uint64_t session_id;
531 uint8_t res[16];
532 NTSTATUS status;
535 * We expect
536 * - SMB2 HDR
537 * - SMB2 BODY FIXED
538 * - (optional) SMB2 BODY DYN
539 * - (optional) PADDING
541 SMB_ASSERT(count >= 2);
542 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
543 SMB_ASSERT(count <= 4);
545 hdr = (uint8_t *)vector[0].iov_base;
547 session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
548 if (session_id == 0) {
550 * do not sign messages with a zero session_id.
551 * See MS-SMB2 3.2.4.1.1
553 return NT_STATUS_OK;
556 if (!smb2_signing_key_valid(signing_key)) {
557 DBG_WARNING("No signing key for SMB2 signing\n");
558 return NT_STATUS_ACCESS_DENIED;
561 memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
563 SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
565 sign_algo_id = signing_key->sign_algo_id;
567 status = smb2_signing_calc_signature(signing_key,
568 sign_algo_id,
569 vector,
570 count,
571 res);
572 if (!NT_STATUS_IS_OK(status)) {
573 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
574 (unsigned)sign_algo_id, nt_errstr(status));
575 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
576 smb_panic(__location__);
578 return status;
581 DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
582 (unsigned)sign_algo_id));
584 memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
586 return NT_STATUS_OK;
589 NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
590 const struct iovec *vector,
591 int count)
593 uint16_t sign_algo_id;
594 const uint8_t *hdr;
595 const uint8_t *sig;
596 uint64_t session_id;
597 uint8_t res[16];
598 NTSTATUS status;
601 * We expect
602 * - SMB2 HDR
603 * - SMB2 BODY FIXED
604 * - (optional) SMB2 BODY DYN
605 * - (optional) PADDING
607 SMB_ASSERT(count >= 2);
608 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
609 SMB_ASSERT(count <= 4);
611 hdr = (const uint8_t *)vector[0].iov_base;
613 session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
614 if (session_id == 0) {
616 * do not sign messages with a zero session_id.
617 * See MS-SMB2 3.2.4.1.1
619 return NT_STATUS_OK;
622 if (!smb2_signing_key_valid(signing_key)) {
623 /* we don't have the session key yet */
624 return NT_STATUS_OK;
627 sig = hdr+SMB2_HDR_SIGNATURE;
629 sign_algo_id = signing_key->sign_algo_id;
631 status = smb2_signing_calc_signature(signing_key,
632 sign_algo_id,
633 vector,
634 count,
635 res);
636 if (!NT_STATUS_IS_OK(status)) {
637 DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
638 (unsigned)sign_algo_id, nt_errstr(status));
639 if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
640 status = NT_STATUS_ACCESS_DENIED;
642 return status;
645 if (!mem_equal_const_time(res, sig, 16)) {
646 DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
647 (unsigned)sign_algo_id));
648 dump_data(0, sig, 16);
649 dump_data(0, res, 16);
650 return NT_STATUS_ACCESS_DENIED;
653 return NT_STATUS_OK;
656 NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
657 struct iovec *vector,
658 int count)
660 bool use_encryptv2 = false;
661 uint16_t cipher_id;
662 uint8_t *tf;
663 size_t a_total;
664 ssize_t m_total;
665 uint32_t iv_size = 0;
666 uint32_t key_size = 0;
667 size_t tag_size = 0;
668 gnutls_cipher_algorithm_t algo = 0;
669 gnutls_datum_t key;
670 gnutls_datum_t iv;
671 NTSTATUS status;
672 int rc;
674 if (count < 1) {
675 return NT_STATUS_INVALID_PARAMETER;
678 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
679 return NT_STATUS_INVALID_PARAMETER;
682 tf = (uint8_t *)vector[0].iov_base;
684 if (!smb2_signing_key_valid(encryption_key)) {
685 DBG_WARNING("No encryption key for SMB2 signing\n");
686 return NT_STATUS_ACCESS_DENIED;
688 cipher_id = encryption_key->cipher_algo_id;
690 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
692 m_total = iov_buflen(&vector[1], count-1);
693 if (m_total == -1) {
694 return NT_STATUS_BUFFER_TOO_SMALL;
697 SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
698 SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
700 switch (cipher_id) {
701 case SMB2_ENCRYPTION_AES128_CCM:
702 algo = GNUTLS_CIPHER_AES_128_CCM;
703 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
704 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
705 use_encryptv2 = true;
706 #endif
707 break;
708 case SMB2_ENCRYPTION_AES128_GCM:
709 algo = GNUTLS_CIPHER_AES_128_GCM;
710 iv_size = gnutls_cipher_get_iv_size(algo);
711 use_encryptv2 = true;
712 break;
713 case SMB2_ENCRYPTION_AES256_CCM:
714 algo = GNUTLS_CIPHER_AES_256_CCM;
715 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
716 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
717 use_encryptv2 = true;
718 #endif
719 break;
720 case SMB2_ENCRYPTION_AES256_GCM:
721 algo = GNUTLS_CIPHER_AES_256_GCM;
722 iv_size = gnutls_cipher_get_iv_size(algo);
723 use_encryptv2 = true;
724 break;
725 default:
726 return NT_STATUS_INVALID_PARAMETER;
729 key_size = gnutls_cipher_get_key_size(algo);
730 tag_size = gnutls_cipher_get_tag_size(algo);
732 if (key_size != encryption_key->blob.length) {
733 return NT_STATUS_INTERNAL_ERROR;
736 if (tag_size != 16) {
737 return NT_STATUS_INTERNAL_ERROR;
740 key = (gnutls_datum_t) {
741 .data = encryption_key->blob.data,
742 .size = key_size,
745 iv = (gnutls_datum_t) {
746 .data = tf + SMB2_TF_NONCE,
747 .size = iv_size,
750 if (encryption_key->cipher_hnd == NULL) {
751 rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
752 algo,
753 &key);
754 if (rc < 0) {
755 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
756 goto out;
760 memset(tf + SMB2_TF_NONCE + iv_size,
762 16 - iv_size);
764 if (use_encryptv2) {
765 uint8_t tag[tag_size];
766 giovec_t auth_iov[1];
768 auth_iov[0] = (giovec_t) {
769 .iov_base = tf + SMB2_TF_NONCE,
770 .iov_len = a_total,
773 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
774 iv.data,
775 iv.size,
776 auth_iov,
778 &vector[1],
779 count - 1,
780 tag,
781 &tag_size);
782 if (rc < 0) {
783 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
784 goto out;
787 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
788 } else
790 size_t ptext_size = m_total;
791 uint8_t *ptext = NULL;
792 size_t ctext_size = m_total + tag_size;
793 uint8_t *ctext = NULL;
794 size_t len = 0;
795 int i;
796 TALLOC_CTX *tmp_ctx = NULL;
799 * If we come from python bindings, we don't have a stackframe
800 * around, so use the NULL context.
802 * This is fine as we make sure we free the memory.
804 if (talloc_stackframe_exists()) {
805 tmp_ctx = talloc_tos();
808 ptext = talloc_size(tmp_ctx, ptext_size);
809 if (ptext == NULL) {
810 status = NT_STATUS_NO_MEMORY;
811 goto out;
814 ctext = talloc_size(tmp_ctx, ctext_size);
815 if (ctext == NULL) {
816 TALLOC_FREE(ptext);
817 status = NT_STATUS_NO_MEMORY;
818 goto out;
821 for (i = 1; i < count; i++) {
822 if (vector[i].iov_base != NULL) {
823 memcpy(ptext + len,
824 vector[i].iov_base,
825 vector[i].iov_len);
828 len += vector[i].iov_len;
829 if (len > ptext_size) {
830 TALLOC_FREE(ptext);
831 TALLOC_FREE(ctext);
832 status = NT_STATUS_INTERNAL_ERROR;
833 goto out;
837 rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
838 iv.data,
839 iv.size,
840 tf + SMB2_TF_NONCE,
841 a_total,
842 tag_size,
843 ptext,
844 ptext_size,
845 ctext,
846 &ctext_size);
847 if (rc < 0 || ctext_size != m_total + tag_size) {
848 TALLOC_FREE(ptext);
849 TALLOC_FREE(ctext);
850 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
851 goto out;
854 len = 0;
855 for (i = 1; i < count; i++) {
856 if (vector[i].iov_base != NULL) {
857 memcpy(vector[i].iov_base,
858 ctext + len,
859 vector[i].iov_len);
862 len += vector[i].iov_len;
865 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
867 TALLOC_FREE(ptext);
868 TALLOC_FREE(ctext);
871 DBG_INFO("Encrypted SMB2 message\n");
873 status = NT_STATUS_OK;
874 out:
875 return status;
878 NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
879 struct iovec *vector,
880 int count)
882 bool use_encryptv2 = false;
883 uint16_t cipher_id;
884 uint8_t *tf;
885 uint16_t flags;
886 size_t a_total;
887 ssize_t m_total;
888 uint32_t msg_size = 0;
889 uint32_t iv_size = 0;
890 uint32_t key_size = 0;
891 size_t tag_size = 0;
892 gnutls_cipher_algorithm_t algo = 0;
893 gnutls_datum_t key;
894 gnutls_datum_t iv;
895 NTSTATUS status;
896 int rc;
898 if (count < 1) {
899 return NT_STATUS_INVALID_PARAMETER;
902 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
903 return NT_STATUS_INVALID_PARAMETER;
906 tf = (uint8_t *)vector[0].iov_base;
908 if (!smb2_signing_key_valid(decryption_key)) {
909 DBG_WARNING("No decryption key for SMB2 signing\n");
910 return NT_STATUS_ACCESS_DENIED;
912 cipher_id = decryption_key->cipher_algo_id;
914 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
916 m_total = iov_buflen(&vector[1], count-1);
917 if (m_total == -1) {
918 return NT_STATUS_BUFFER_TOO_SMALL;
921 flags = SVAL(tf, SMB2_TF_FLAGS);
922 msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
924 if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
925 return NT_STATUS_ACCESS_DENIED;
928 if (msg_size != m_total) {
929 return NT_STATUS_INTERNAL_ERROR;
932 switch (cipher_id) {
933 case SMB2_ENCRYPTION_AES128_CCM:
934 algo = GNUTLS_CIPHER_AES_128_CCM;
935 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
936 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
937 use_encryptv2 = true;
938 #endif
939 break;
940 case SMB2_ENCRYPTION_AES128_GCM:
941 algo = GNUTLS_CIPHER_AES_128_GCM;
942 iv_size = gnutls_cipher_get_iv_size(algo);
943 use_encryptv2 = true;
944 break;
945 case SMB2_ENCRYPTION_AES256_CCM:
946 algo = GNUTLS_CIPHER_AES_256_CCM;
947 iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
948 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
949 use_encryptv2 = true;
950 #endif
951 break;
952 case SMB2_ENCRYPTION_AES256_GCM:
953 algo = GNUTLS_CIPHER_AES_256_GCM;
954 iv_size = gnutls_cipher_get_iv_size(algo);
955 use_encryptv2 = true;
956 break;
957 default:
958 return NT_STATUS_INVALID_PARAMETER;
961 key_size = gnutls_cipher_get_key_size(algo);
962 tag_size = gnutls_cipher_get_tag_size(algo);
964 if (key_size != decryption_key->blob.length) {
965 return NT_STATUS_INTERNAL_ERROR;
968 if (tag_size != 16) {
969 return NT_STATUS_INTERNAL_ERROR;
972 key = (gnutls_datum_t) {
973 .data = decryption_key->blob.data,
974 .size = key_size,
977 iv = (gnutls_datum_t) {
978 .data = tf + SMB2_TF_NONCE,
979 .size = iv_size,
982 if (decryption_key->cipher_hnd == NULL) {
983 rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
984 algo,
985 &key);
986 if (rc < 0) {
987 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
988 goto out;
992 if (use_encryptv2) {
993 giovec_t auth_iov[1];
995 auth_iov[0] = (giovec_t) {
996 .iov_base = tf + SMB2_TF_NONCE,
997 .iov_len = a_total,
1000 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
1001 iv.data,
1002 iv.size,
1003 auth_iov,
1005 &vector[1],
1006 count - 1,
1007 tf + SMB2_TF_SIGNATURE,
1008 tag_size);
1009 if (rc < 0) {
1010 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1011 goto out;
1013 } else
1015 size_t ctext_size = m_total + tag_size;
1016 uint8_t *ctext = NULL;
1017 size_t ptext_size = m_total;
1018 uint8_t *ptext = NULL;
1019 size_t len = 0;
1020 int i;
1021 TALLOC_CTX *tmp_ctx = NULL;
1024 * If we come from python bindings, we don't have a stackframe
1025 * around, so use the NULL context.
1027 * This is fine as we make sure we free the memory.
1029 if (talloc_stackframe_exists()) {
1030 tmp_ctx = talloc_tos();
1033 /* GnuTLS doesn't have a iovec API for decryption yet */
1035 ptext = talloc_size(tmp_ctx, ptext_size);
1036 if (ptext == NULL) {
1037 status = NT_STATUS_NO_MEMORY;
1038 goto out;
1041 ctext = talloc_size(tmp_ctx, ctext_size);
1042 if (ctext == NULL) {
1043 TALLOC_FREE(ptext);
1044 status = NT_STATUS_NO_MEMORY;
1045 goto out;
1049 for (i = 1; i < count; i++) {
1050 memcpy(ctext + len,
1051 vector[i].iov_base,
1052 vector[i].iov_len);
1054 len += vector[i].iov_len;
1056 if (len != m_total) {
1057 TALLOC_FREE(ptext);
1058 TALLOC_FREE(ctext);
1059 status = NT_STATUS_INTERNAL_ERROR;
1060 goto out;
1063 memcpy(ctext + len,
1064 tf + SMB2_TF_SIGNATURE,
1065 tag_size);
1067 /* This function will verify the tag */
1068 rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
1069 iv.data,
1070 iv.size,
1071 tf + SMB2_TF_NONCE,
1072 a_total,
1073 tag_size,
1074 ctext,
1075 ctext_size,
1076 ptext,
1077 &ptext_size);
1078 if (rc < 0) {
1079 TALLOC_FREE(ptext);
1080 TALLOC_FREE(ctext);
1081 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1082 goto out;
1084 if (ptext_size != m_total) {
1085 TALLOC_FREE(ptext);
1086 TALLOC_FREE(ctext);
1087 rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
1088 status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1089 goto out;
1092 len = 0;
1093 for (i = 1; i < count; i++) {
1094 memcpy(vector[i].iov_base,
1095 ptext + len,
1096 vector[i].iov_len);
1098 len += vector[i].iov_len;
1101 TALLOC_FREE(ptext);
1102 TALLOC_FREE(ctext);
1105 DBG_INFO("Decrypted SMB2 message\n");
1107 status = NT_STATUS_OK;
1108 out:
1109 return status;