s3: smbd: Fix schedule_smb2_aio_read() to allow the last read in a compound to go...
[Samba.git] / libcli / smb / smb2_signing.c
blobd95274c169294c80afd324e00d543ddc297aea12
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:
190 case SMB2_SIGNING_AES128_GMAC:
192 * signing keys are padded or truncated to
193 * 16 bytes.
195 * Even with master_key->length = 0,
196 * we need to use 16 zeros.
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;
204 switch (cipher_algo_id) {
205 case SMB2_ENCRYPTION_INVALID_ALGO:
207 * This means we're processing sign_algo_id above
209 break;
210 case SMB2_ENCRYPTION_NONE:
212 * No encryption negotiated.
214 break;
215 case SMB2_ENCRYPTION_AES128_CCM:
216 case SMB2_ENCRYPTION_AES128_GCM:
218 * encryption keys are padded or truncated to
219 * 16 bytes.
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;
226 in_key_length = out_key_length = 16;
227 break;
228 case SMB2_ENCRYPTION_AES256_CCM:
229 case SMB2_ENCRYPTION_AES256_GCM:
231 * AES256 uses the available input and
232 * generated a 32 byte encryption key.
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;
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;
246 if (out_key_length == 0) {
247 *_key = key;
248 return NT_STATUS_OK;
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;
256 talloc_keep_secret(key->blob.data);
257 memcpy(key->blob.data,
258 master_key->data,
259 MIN(key->blob.length, master_key->length));
261 if (d == NULL) {
262 *_key = key;
263 return NT_STATUS_OK;
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;
275 *_key = key;
276 return NT_STATUS_OK;
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)
285 return smb2_signing_key_create(mem_ctx,
286 sign_algo_id,
287 SMB2_ENCRYPTION_INVALID_ALGO,
288 master_key,
290 _key);
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)
299 return smb2_signing_key_create(mem_ctx,
300 SMB2_SIGNING_INVALID_ALGO,
301 cipher_algo_id,
302 master_key,
304 _key);
307 bool smb2_signing_key_valid(const struct smb2_signing_key *key)
309 if (key == NULL) {
310 return false;
313 if (key->blob.length == 0 || key->blob.data == NULL) {
314 return false;
317 return true;
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)
325 size_t tag_size = _tag_size;
326 int rc;
327 #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
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);
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;
347 * If we come from python bindings, we don't have a stackframe
348 * around, so use the NULL context.
350 * This is fine as we make sure we free the memory.
352 if (talloc_stackframe_exists()) {
353 tmp_ctx = talloc_tos();
356 for (i=0; i < auth_iovcnt; i++) {
357 atext_size += auth_iov[i].iov_len;
360 atext = talloc_size(tmp_ctx, atext_size);
361 if (atext == NULL) {
362 return NT_STATUS_NO_MEMORY;
365 for (i = 0; i < auth_iovcnt; i++) {
366 memcpy(atext + len,
367 auth_iov[i].iov_base,
368 auth_iov[i].iov_len);
370 len += auth_iov[i].iov_len;
371 if (len > atext_size) {
372 TALLOC_FREE(atext);
373 return NT_STATUS_INTERNAL_ERROR;
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);
389 return NT_STATUS_OK;
390 #endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
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])
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;
408 * We expect
409 * - SMB2 HDR
410 * - SMB2 BODY FIXED
411 * - (optional) SMB2 BODY DYN
412 * - (optional) PADDING
414 SMB_ASSERT(count >= 2);
415 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
416 SMB_ASSERT(count <= 4);
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;
426 if (opcode == SMB2_OP_CANCEL) {
427 DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
428 return NT_STATUS_INTERNAL_ERROR;
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)
436 DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
437 return NT_STATUS_INTERNAL_ERROR;
440 * Legacy algorithms allow MID 0
441 * for cancel requests
444 if (msg_id == UINT64_MAX) {
445 DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
446 return NT_STATUS_INTERNAL_ERROR;
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),
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;
466 high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
467 if (opcode == SMB2_OP_CANCEL) {
468 high_bits |= SMB2_HDR_FLAG_ASYNC;
470 SBVAL(iv, 0, msg_id);
471 SBVAL(iv, 8, high_bits);
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);
483 SMB_ASSERT(key_size == 16);
484 SMB_ASSERT(iv_size == 12);
485 SMB_ASSERT(tag_size == 16);
487 auth_iov[auth_iovcnt++] = (giovec_t) {
488 .iov_base = discard_const_p(uint8_t, hdr),
489 .iov_len = SMB2_HDR_SIGNATURE,
491 auth_iov[auth_iovcnt++] = (giovec_t) {
492 .iov_base = discard_const_p(uint8_t, zero_sig),
493 .iov_len = 16,
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,
502 status = smb2_signing_gmac(signing_key->cipher_hnd,
504 iv_size,
505 auth_iov,
506 auth_iovcnt,
507 signature,
508 tag_size);
509 if (!NT_STATUS_IS_OK(status)) {
510 return status;
513 return NT_STATUS_OK;
514 } break;
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 */
522 struct aes_cmac_128_context ctx;
523 uint8_t key[AES_BLOCK_SIZE] = {0};
525 memcpy(key,
526 signing_key->blob.data,
527 MIN(signing_key->blob.length, 16));
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);
537 aes_cmac_128_final(&ctx, signature);
539 ZERO_ARRAY(key);
541 return NT_STATUS_OK;
542 } break;
543 #endif
544 case SMB2_SIGNING_HMAC_SHA256:
545 hmac_algo = GNUTLS_MAC_SHA256;
546 break;
548 default:
549 return NT_STATUS_HMAC_NOT_SUPPORTED;
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),
558 int rc;
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);
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);
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);
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);
591 gnutls_hmac_output(signing_key->hmac_hnd, digest);
592 memcpy(signature, digest, 16);
593 ZERO_ARRAY(digest);
594 return NT_STATUS_OK;
597 return NT_STATUS_HMAC_NOT_SUPPORTED;
600 NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
601 struct iovec *vector,
602 int count)
604 uint16_t sign_algo_id;
605 uint8_t *hdr;
606 uint64_t session_id;
607 uint8_t res[16];
608 NTSTATUS status;
611 * We expect
612 * - SMB2 HDR
613 * - SMB2 BODY FIXED
614 * - (optional) SMB2 BODY DYN
615 * - (optional) PADDING
617 SMB_ASSERT(count >= 2);
618 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
619 SMB_ASSERT(count <= 4);
621 hdr = (uint8_t *)vector[0].iov_base;
623 session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
624 if (session_id == 0) {
626 * do not sign messages with a zero session_id.
627 * See MS-SMB2 3.2.4.1.1
629 return NT_STATUS_OK;
632 if (!smb2_signing_key_valid(signing_key)) {
633 DBG_WARNING("No signing key for SMB2 signing\n");
634 return NT_STATUS_ACCESS_DENIED;
637 memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
639 SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
641 sign_algo_id = signing_key->sign_algo_id;
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__);
654 return status;
657 DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
658 (unsigned)sign_algo_id));
660 memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
662 return NT_STATUS_OK;
665 NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
666 const struct iovec *vector,
667 int count)
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;
677 * We expect
678 * - SMB2 HDR
679 * - SMB2 BODY FIXED
680 * - (optional) SMB2 BODY DYN
681 * - (optional) PADDING
683 SMB_ASSERT(count >= 2);
684 SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
685 SMB_ASSERT(count <= 4);
687 hdr = (const uint8_t *)vector[0].iov_base;
689 session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
690 if (session_id == 0) {
692 * do not sign messages with a zero session_id.
693 * See MS-SMB2 3.2.4.1.1
695 return NT_STATUS_OK;
698 if (!smb2_signing_key_valid(signing_key)) {
699 /* we don't have the session key yet */
700 return NT_STATUS_OK;
703 sig = hdr+SMB2_HDR_SIGNATURE;
705 sign_algo_id = signing_key->sign_algo_id;
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;
718 return status;
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;
729 return NT_STATUS_OK;
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)
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;
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;
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;
761 * a simplified version of
762 * "NIST Special Publication 800-108" section 5.1
763 * using hmac-sha256.
765 rc = gnutls_hmac_init(&hmac_hnd,
766 GNUTLS_MAC_SHA256,
768 KI_len);
769 if (rc < 0) {
770 return gnutls_error_to_ntstatus(rc,
771 NT_STATUS_HMAC_NOT_SUPPORTED);
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);
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);
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);
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);
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);
806 gnutls_hmac_deinit(hmac_hnd, digest);
808 memcpy(KO, digest, KO_len);
810 ZERO_ARRAY(digest);
812 return NT_STATUS_OK;
815 NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
816 struct iovec *vector,
817 int count)
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;
835 if (count < 1) {
836 return NT_STATUS_INVALID_PARAMETER;
839 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
840 return NT_STATUS_INVALID_PARAMETER;
843 tf = (uint8_t *)vector[0].iov_base;
845 if (!smb2_signing_key_valid(encryption_key)) {
846 DBG_WARNING("No encryption key for SMB2 signing\n");
847 return NT_STATUS_ACCESS_DENIED;
849 cipher_id = encryption_key->cipher_algo_id;
851 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
853 m_total = iov_buflen(&vector[1], count-1);
854 if (m_total == -1) {
855 return NT_STATUS_BUFFER_TOO_SMALL;
858 SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
859 SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
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;
894 key_size = gnutls_cipher_get_key_size(algo);
895 tag_size = gnutls_cipher_get_tag_size(algo);
897 if (key_size != encryption_key->blob.length) {
898 return NT_STATUS_INTERNAL_ERROR;
901 if (tag_size != 16) {
902 return NT_STATUS_INTERNAL_ERROR;
905 key = (gnutls_datum_t) {
906 .data = encryption_key->blob.data,
907 .size = key_size,
910 iv = (gnutls_datum_t) {
911 .data = tf + SMB2_TF_NONCE,
912 .size = iv_size,
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;
925 memset(tf + SMB2_TF_NONCE + iv_size,
927 16 - iv_size);
929 #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
930 if (use_encryptv2) {
931 uint8_t tag[tag_size];
932 giovec_t auth_iov[1];
934 auth_iov[0] = (giovec_t) {
935 .iov_base = tf + SMB2_TF_NONCE,
936 .iov_len = a_total,
939 rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
940 iv.data,
941 iv.size,
942 auth_iov,
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;
953 memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
954 } else
955 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
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;
966 * If we come from python bindings, we don't have a stackframe
967 * around, so use the NULL context.
969 * This is fine as we make sure we free the memory.
971 if (talloc_stackframe_exists()) {
972 tmp_ctx = talloc_tos();
975 ptext = talloc_size(tmp_ctx, ptext_size);
976 if (ptext == NULL) {
977 status = NT_STATUS_NO_MEMORY;
978 goto out;
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;
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);
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;
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;
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);
1029 len += vector[i].iov_len;
1032 memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
1034 TALLOC_FREE(ptext);
1035 TALLOC_FREE(ctext);
1038 DBG_INFO("Encrypted SMB2 message\n");
1040 status = NT_STATUS_OK;
1041 out:
1042 return status;
1045 NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
1046 struct iovec *vector,
1047 int count)
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;
1067 if (count < 1) {
1068 return NT_STATUS_INVALID_PARAMETER;
1071 if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
1072 return NT_STATUS_INVALID_PARAMETER;
1075 tf = (uint8_t *)vector[0].iov_base;
1077 if (!smb2_signing_key_valid(decryption_key)) {
1078 DBG_WARNING("No decryption key for SMB2 signing\n");
1079 return NT_STATUS_ACCESS_DENIED;
1081 cipher_id = decryption_key->cipher_algo_id;
1083 a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
1085 m_total = iov_buflen(&vector[1], count-1);
1086 if (m_total == -1) {
1087 return NT_STATUS_BUFFER_TOO_SMALL;
1090 flags = SVAL(tf, SMB2_TF_FLAGS);
1091 msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
1093 if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
1094 return NT_STATUS_ACCESS_DENIED;
1097 if (msg_size != m_total) {
1098 return NT_STATUS_INTERNAL_ERROR;
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;
1134 key_size = gnutls_cipher_get_key_size(algo);
1135 tag_size = gnutls_cipher_get_tag_size(algo);
1137 if (key_size != decryption_key->blob.length) {
1138 return NT_STATUS_INTERNAL_ERROR;
1141 if (tag_size != 16) {
1142 return NT_STATUS_INTERNAL_ERROR;
1145 key = (gnutls_datum_t) {
1146 .data = decryption_key->blob.data,
1147 .size = key_size,
1150 iv = (gnutls_datum_t) {
1151 .data = tf + SMB2_TF_NONCE,
1152 .size = iv_size,
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;
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];
1170 auth_iov[0] = (giovec_t) {
1171 .iov_base = tf + SMB2_TF_NONCE,
1172 .iov_len = a_total,
1175 rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
1176 iv.data,
1177 iv.size,
1178 auth_iov,
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;
1188 } else
1189 #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
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;
1200 * If we come from python bindings, we don't have a stackframe
1201 * around, so use the NULL context.
1203 * This is fine as we make sure we free the memory.
1205 if (talloc_stackframe_exists()) {
1206 tmp_ctx = talloc_tos();
1209 /* GnuTLS doesn't have a iovec API for decryption yet */
1211 ptext = talloc_size(tmp_ctx, ptext_size);
1212 if (ptext == NULL) {
1213 status = NT_STATUS_NO_MEMORY;
1214 goto out;
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;
1225 for (i = 1; i < count; i++) {
1226 memcpy(ctext + len,
1227 vector[i].iov_base,
1228 vector[i].iov_len);
1230 len += vector[i].iov_len;
1232 if (len != m_total) {
1233 TALLOC_FREE(ptext);
1234 TALLOC_FREE(ctext);
1235 status = NT_STATUS_INTERNAL_ERROR;
1236 goto out;
1239 memcpy(ctext + len,
1240 tf + SMB2_TF_SIGNATURE,
1241 tag_size);
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;
1260 #ifdef HAVE_GNUTLS_AEAD_CIPHER_DECRYPT_PTEXT_LEN_BUG
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
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;
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;
1283 len = 0;
1284 for (i = 1; i < count; i++) {
1285 memcpy(vector[i].iov_base,
1286 ptext + len,
1287 vector[i].iov_len);
1289 len += vector[i].iov_len;
1292 TALLOC_FREE(ptext);
1293 TALLOC_FREE(ctext);
1296 DBG_INFO("Decrypted SMB2 message\n");
1298 status = NT_STATUS_OK;
1299 out:
1300 return status;