Line data Source code
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 42490 : 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 42490 : *ds = (struct smb2_signing_derivations) { .signing = NULL, };
42 :
43 42490 : if (protocol >= PROTOCOL_SMB3_11) {
44 36246 : struct smb2_signing_derivation *d = NULL;
45 :
46 36246 : SMB_ASSERT(preauth_hash.length != 0);
47 :
48 36246 : d = &ds->__signing;
49 36246 : ds->signing = d;
50 36246 : d->label = data_blob_string_const_null("SMBSigningKey");
51 36246 : d->context = preauth_hash;
52 :
53 36246 : d = &ds->__cipher_c2s;
54 36246 : ds->cipher_c2s = d;
55 36246 : d->label = data_blob_string_const_null("SMBC2SCipherKey");
56 36246 : d->context = preauth_hash;
57 :
58 36246 : d = &ds->__cipher_s2c;
59 36246 : ds->cipher_s2c = d;
60 36246 : d->label = data_blob_string_const_null("SMBS2CCipherKey");
61 36246 : d->context = preauth_hash;
62 :
63 36246 : d = &ds->__application;
64 36246 : ds->application = d;
65 36246 : d->label = data_blob_string_const_null("SMBAppKey");
66 36246 : d->context = preauth_hash;
67 :
68 6244 : } else if (protocol >= PROTOCOL_SMB3_00) {
69 112 : struct smb2_signing_derivation *d = NULL;
70 :
71 112 : d = &ds->__signing;
72 112 : ds->signing = d;
73 112 : d->label = data_blob_string_const_null("SMB2AESCMAC");
74 112 : d->context = data_blob_string_const_null("SmbSign");
75 :
76 112 : d = &ds->__cipher_c2s;
77 112 : ds->cipher_c2s = d;
78 112 : d->label = data_blob_string_const_null("SMB2AESCCM");
79 112 : d->context = data_blob_string_const_null("ServerIn ");
80 :
81 112 : d = &ds->__cipher_s2c;
82 112 : ds->cipher_s2c = d;
83 112 : d->label = data_blob_string_const_null("SMB2AESCCM");
84 112 : d->context = data_blob_string_const_null("ServerOut");
85 :
86 112 : d = &ds->__application;
87 112 : ds->application = d;
88 112 : d->label = data_blob_string_const_null("SMB2APP");
89 112 : d->context = data_blob_string_const_null("SmbRpc");
90 : }
91 42490 : }
92 :
93 278619 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
94 : {
95 278619 : if (key->hmac_hnd != NULL) {
96 6766 : gnutls_hmac_deinit(key->hmac_hnd, NULL);
97 6766 : key->hmac_hnd = NULL;
98 : }
99 :
100 278619 : if (key->cipher_hnd != NULL) {
101 40747 : gnutls_aead_cipher_deinit(key->cipher_hnd);
102 40747 : key->cipher_hnd = NULL;
103 : }
104 :
105 278619 : return 0;
106 : }
107 :
108 46794 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
109 : const struct smb2_signing_key *src,
110 : struct smb2_signing_key **_dst)
111 : {
112 46794 : struct smb2_signing_key *dst = NULL;
113 :
114 46794 : dst = talloc_zero(mem_ctx, struct smb2_signing_key);
115 46794 : if (dst == NULL) {
116 0 : return NT_STATUS_NO_MEMORY;
117 : }
118 46794 : talloc_set_destructor(dst, smb2_signing_key_destructor);
119 :
120 46794 : dst->sign_algo_id = src->sign_algo_id;
121 46794 : dst->cipher_algo_id = src->cipher_algo_id;
122 :
123 46794 : if (src->blob.length == 0) {
124 0 : *_dst = dst;
125 0 : return NT_STATUS_OK;
126 : }
127 :
128 46794 : dst->blob = data_blob_talloc_zero(dst, src->blob.length);
129 46794 : if (dst->blob.length == 0) {
130 0 : TALLOC_FREE(dst);
131 0 : return NT_STATUS_NO_MEMORY;
132 : }
133 46794 : talloc_keep_secret(dst->blob.data);
134 47572 : memcpy(dst->blob.data, src->blob.data, dst->blob.length);
135 :
136 46794 : *_dst = dst;
137 46794 : return NT_STATUS_OK;
138 : }
139 :
140 257725 : 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 257725 : struct smb2_signing_key *key = NULL;
148 257725 : size_t in_key_length = 16;
149 257725 : size_t out_key_length = 16;
150 : NTSTATUS status;
151 :
152 257725 : if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
153 179643 : SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
154 : }
155 257725 : if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
156 78082 : SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
157 : }
158 :
159 257725 : key = talloc_zero(mem_ctx, struct smb2_signing_key);
160 257725 : if (key == NULL) {
161 0 : return NT_STATUS_NO_MEMORY;
162 : }
163 257725 : talloc_set_destructor(key, smb2_signing_key_destructor);
164 :
165 257725 : key->sign_algo_id = sign_algo_id;
166 257725 : key->cipher_algo_id = cipher_algo_id;
167 :
168 257725 : if (master_key == NULL) {
169 91456 : SMB_ASSERT(d == NULL);
170 :
171 91456 : *_key = key;
172 91456 : return NT_STATUS_OK;
173 : }
174 :
175 : /*
176 : * Per default use the full key.
177 : */
178 166269 : in_key_length = out_key_length = master_key->length;
179 166269 : switch (sign_algo_id) {
180 75680 : case SMB2_SIGNING_INVALID_ALGO:
181 : /*
182 : * This means we're processing cipher_algo_id below
183 : */
184 75680 : break;
185 4815 : case SMB2_SIGNING_MD5_SMB1:
186 4815 : SMB_ASSERT(d == NULL);
187 4683 : break;
188 84222 : case SMB2_SIGNING_HMAC_SHA256:
189 : case SMB2_SIGNING_AES128_CMAC:
190 : case SMB2_SIGNING_AES128_GMAC:
191 : /*
192 : * signing keys are padded or truncated to
193 : * 16 bytes.
194 : *
195 : * Even with master_key->length = 0,
196 : * we need to use 16 zeros.
197 : */
198 84222 : in_key_length = out_key_length = 16;
199 84222 : break;
200 0 : default:
201 0 : DBG_ERR("sign_algo_id[%u] not supported\n", sign_algo_id);
202 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
203 : }
204 166269 : switch (cipher_algo_id) {
205 87349 : case SMB2_ENCRYPTION_INVALID_ALGO:
206 : /*
207 : * This means we're processing sign_algo_id above
208 : */
209 87349 : break;
210 8080 : case SMB2_ENCRYPTION_NONE:
211 : /*
212 : * No encryption negotiated.
213 : */
214 8080 : break;
215 69072 : case SMB2_ENCRYPTION_AES128_CCM:
216 : case SMB2_ENCRYPTION_AES128_GCM:
217 : /*
218 : * encryption keys are padded or truncated to
219 : * 16 bytes.
220 : */
221 69072 : if (master_key->length == 0) {
222 0 : DBG_ERR("cipher_algo_id[%u] without key\n",
223 : cipher_algo_id);
224 0 : return NT_STATUS_NO_USER_SESSION_KEY;
225 : }
226 67520 : in_key_length = out_key_length = 16;
227 67520 : break;
228 80 : case SMB2_ENCRYPTION_AES256_CCM:
229 : case SMB2_ENCRYPTION_AES256_GCM:
230 : /*
231 : * AES256 uses the available input and
232 : * generated a 32 byte encryption key.
233 : */
234 80 : if (master_key->length == 0) {
235 0 : DBG_ERR("cipher_algo_id[%u] without key\n",
236 : cipher_algo_id);
237 0 : return NT_STATUS_NO_USER_SESSION_KEY;
238 : }
239 80 : out_key_length = 32;
240 80 : break;
241 0 : default:
242 0 : DBG_ERR("cipher_algo_id[%u] not supported\n", cipher_algo_id);
243 0 : return NT_STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG;
244 : }
245 :
246 164717 : if (out_key_length == 0) {
247 0 : *_key = key;
248 0 : return NT_STATUS_OK;
249 : }
250 :
251 166269 : key->blob = data_blob_talloc_zero(key, out_key_length);
252 166269 : if (key->blob.length == 0) {
253 0 : TALLOC_FREE(key);
254 0 : return NT_STATUS_NO_MEMORY;
255 : }
256 166269 : talloc_keep_secret(key->blob.data);
257 169509 : memcpy(key->blob.data,
258 166269 : master_key->data,
259 166269 : MIN(key->blob.length, master_key->length));
260 :
261 166269 : if (d == NULL) {
262 24769 : *_key = key;
263 24769 : return NT_STATUS_OK;
264 : }
265 :
266 392152 : status = smb2_key_derivation(key->blob.data, in_key_length,
267 141500 : d->label.data, d->label.length,
268 141500 : d->context.data, d->context.length,
269 : key->blob.data, out_key_length);
270 141500 : if (!NT_STATUS_IS_OK(status)) {
271 0 : TALLOC_FREE(key);
272 0 : return status;
273 : }
274 :
275 141500 : *_key = key;
276 141500 : return NT_STATUS_OK;
277 : }
278 :
279 179643 : NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
280 : uint16_t sign_algo_id,
281 : const DATA_BLOB *master_key,
282 : const struct smb2_signing_derivation *d,
283 : struct smb2_signing_key **_key)
284 : {
285 179643 : return smb2_signing_key_create(mem_ctx,
286 : sign_algo_id,
287 : SMB2_ENCRYPTION_INVALID_ALGO,
288 : master_key,
289 : d,
290 : _key);
291 : }
292 :
293 78082 : NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
294 : uint16_t cipher_algo_id,
295 : const DATA_BLOB *master_key,
296 : const struct smb2_signing_derivation *d,
297 : struct smb2_signing_key **_key)
298 : {
299 78082 : return smb2_signing_key_create(mem_ctx,
300 : SMB2_SIGNING_INVALID_ALGO,
301 : cipher_algo_id,
302 : master_key,
303 : d,
304 : _key);
305 : }
306 :
307 9591459 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
308 : {
309 9591459 : if (key == NULL) {
310 776095 : return false;
311 : }
312 :
313 8814178 : if (key->blob.length == 0 || key->blob.data == NULL) {
314 244246 : return false;
315 : }
316 :
317 8567198 : return true;
318 : }
319 :
320 2306547 : static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd,
321 : const uint8_t *iv, size_t iv_size,
322 : const giovec_t *auth_iov, uint8_t auth_iovcnt,
323 : uint8_t *tag, size_t _tag_size)
324 : {
325 2306547 : size_t tag_size = _tag_size;
326 : int rc;
327 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
328 :
329 692105 : rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
330 : iv, iv_size,
331 : auth_iov, auth_iovcnt,
332 : NULL, 0,
333 : tag, &tag_size);
334 692105 : if (rc < 0) {
335 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
336 : }
337 :
338 692105 : return NT_STATUS_OK;
339 : #else /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
340 1614442 : TALLOC_CTX *tmp_ctx = NULL;
341 1614442 : size_t atext_size = 0;
342 1614442 : uint8_t *atext = NULL;
343 1614442 : size_t len = 0;
344 : size_t i;
345 :
346 : /*
347 : * If we come from python bindings, we don't have a stackframe
348 : * around, so use the NULL context.
349 : *
350 : * This is fine as we make sure we free the memory.
351 : */
352 1614442 : if (talloc_stackframe_exists()) {
353 1614224 : tmp_ctx = talloc_tos();
354 : }
355 :
356 8058344 : for (i=0; i < auth_iovcnt; i++) {
357 6443902 : atext_size += auth_iov[i].iov_len;
358 : }
359 :
360 1614442 : atext = talloc_size(tmp_ctx, atext_size);
361 1614442 : if (atext == NULL) {
362 0 : return NT_STATUS_NO_MEMORY;
363 : }
364 :
365 8025166 : for (i = 0; i < auth_iovcnt; i++) {
366 13019994 : memcpy(atext + len,
367 6443902 : auth_iov[i].iov_base,
368 6443902 : auth_iov[i].iov_len);
369 :
370 6443902 : len += auth_iov[i].iov_len;
371 6443902 : if (len > atext_size) {
372 0 : TALLOC_FREE(atext);
373 0 : return NT_STATUS_INTERNAL_ERROR;
374 : }
375 : }
376 :
377 1614442 : 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 1614442 : TALLOC_FREE(atext);
385 1614442 : if (rc < 0) {
386 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
387 : }
388 :
389 1614442 : return NT_STATUS_OK;
390 : #endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */
391 : }
392 :
393 3377909 : static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
394 : uint16_t sign_algo_id,
395 : const struct iovec *vector,
396 : int count,
397 : uint8_t signature[16])
398 : {
399 3377909 : 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 3377909 : gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
405 : int i;
406 :
407 : /*
408 : * We expect
409 : * - SMB2 HDR
410 : * - SMB2 BODY FIXED
411 : * - (optional) SMB2 BODY DYN
412 : * - (optional) PADDING
413 : */
414 3377909 : SMB_ASSERT(count >= 2);
415 3377909 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
416 3377909 : SMB_ASSERT(count <= 4);
417 :
418 3377909 : opcode = SVAL(hdr, SMB2_HDR_OPCODE);
419 3377909 : flags = IVAL(hdr, SMB2_HDR_FLAGS);
420 3377909 : if (flags & SMB2_HDR_FLAG_REDIRECT) {
421 1705704 : NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
422 1705704 : if (NT_STATUS_EQUAL(pdu_status, NT_STATUS_PENDING)) {
423 0 : DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode);
424 0 : return NT_STATUS_INTERNAL_ERROR;
425 : }
426 1705704 : if (opcode == SMB2_OP_CANCEL) {
427 0 : DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
428 0 : return NT_STATUS_INTERNAL_ERROR;
429 : }
430 : }
431 3377909 : msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
432 3377909 : if (msg_id == 0) {
433 0 : DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
434 0 : return NT_STATUS_INTERNAL_ERROR;
435 : }
436 3377909 : if (msg_id == UINT64_MAX) {
437 0 : DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
438 0 : return NT_STATUS_INTERNAL_ERROR;
439 : }
440 :
441 3377909 : switch (sign_algo_id) {
442 2306547 : case SMB2_SIGNING_AES128_GMAC: {
443 2306547 : gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
444 2306547 : uint32_t key_size = gnutls_cipher_get_key_size(algo);
445 2306547 : uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
446 2306547 : size_t tag_size = gnutls_cipher_get_tag_size(algo);
447 3920989 : gnutls_datum_t key = {
448 2306547 : .data = signing_key->blob.data,
449 2306547 : .size = MIN(signing_key->blob.length, key_size),
450 : };
451 2306547 : uint64_t high_bits = 0;
452 2306547 : uint8_t iv[AES_BLOCK_SIZE] = {0};
453 2306547 : giovec_t auth_iov[count+1];
454 2306547 : size_t auth_iovcnt = 0;
455 : NTSTATUS status;
456 : int rc;
457 :
458 2306547 : high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
459 2306547 : if (opcode == SMB2_OP_CANCEL) {
460 32 : high_bits |= SMB2_HDR_FLAG_ASYNC;
461 : }
462 2306547 : SBVAL(iv, 0, msg_id);
463 2306547 : SBVAL(iv, 8, high_bits);
464 :
465 2306547 : if (signing_key->cipher_hnd == NULL) {
466 36982 : rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
467 : algo,
468 : &key);
469 36982 : if (rc < 0) {
470 0 : return gnutls_error_to_ntstatus(rc,
471 : NT_STATUS_HMAC_NOT_SUPPORTED);
472 : }
473 : }
474 :
475 2306547 : SMB_ASSERT(key_size == 16);
476 2306547 : SMB_ASSERT(iv_size == 12);
477 2306547 : SMB_ASSERT(tag_size == 16);
478 :
479 2306547 : auth_iov[auth_iovcnt++] = (giovec_t) {
480 : .iov_base = discard_const_p(uint8_t, hdr),
481 : .iov_len = SMB2_HDR_SIGNATURE,
482 : };
483 2306547 : auth_iov[auth_iovcnt++] = (giovec_t) {
484 : .iov_base = discard_const_p(uint8_t, zero_sig),
485 : .iov_len = 16,
486 : };
487 6902080 : for (i=1; i < count; i++) {
488 7810551 : auth_iov[auth_iovcnt++] = (giovec_t) {
489 4595533 : .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
490 4595533 : .iov_len = vector[i].iov_len,
491 : };
492 : }
493 :
494 2306547 : status = smb2_signing_gmac(signing_key->cipher_hnd,
495 : iv,
496 : iv_size,
497 : auth_iov,
498 : auth_iovcnt,
499 : signature,
500 : tag_size);
501 2306547 : if (!NT_STATUS_IS_OK(status)) {
502 0 : return status;
503 : }
504 :
505 2306547 : return NT_STATUS_OK;
506 : } break;
507 :
508 2466 : case SMB2_SIGNING_AES128_CMAC:
509 : #ifdef HAVE_GNUTLS_AES_CMAC
510 831 : hmac_algo = GNUTLS_MAC_AES_CMAC_128;
511 831 : break;
512 : #else /* NOT HAVE_GNUTLS_AES_CMAC */
513 : {
514 : struct aes_cmac_128_context ctx;
515 1635 : uint8_t key[AES_BLOCK_SIZE] = {0};
516 :
517 3270 : memcpy(key,
518 1635 : signing_key->blob.data,
519 1635 : MIN(signing_key->blob.length, 16));
520 :
521 1635 : aes_cmac_128_init(&ctx, key);
522 1635 : aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
523 1635 : aes_cmac_128_update(&ctx, zero_sig, 16);
524 4900 : for (i=1; i < count; i++) {
525 6530 : aes_cmac_128_update(&ctx,
526 3265 : (const uint8_t *)vector[i].iov_base,
527 3265 : vector[i].iov_len);
528 : }
529 1635 : aes_cmac_128_final(&ctx, signature);
530 :
531 1635 : ZERO_ARRAY(key);
532 :
533 1635 : return NT_STATUS_OK;
534 : } break;
535 : #endif
536 1068896 : case SMB2_SIGNING_HMAC_SHA256:
537 1068896 : hmac_algo = GNUTLS_MAC_SHA256;
538 1068896 : break;
539 :
540 0 : default:
541 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
542 : }
543 :
544 1069727 : if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
545 1069727 : uint8_t digest[gnutls_hash_get_len(hmac_algo)];
546 2024599 : gnutls_datum_t key = {
547 1069727 : .data = signing_key->blob.data,
548 1069727 : .size = MIN(signing_key->blob.length, 16),
549 : };
550 : int rc;
551 :
552 1069727 : if (signing_key->hmac_hnd == NULL) {
553 11368 : rc = gnutls_hmac_init(&signing_key->hmac_hnd,
554 : hmac_algo,
555 6810 : key.data,
556 6810 : key.size);
557 6810 : if (rc < 0) {
558 0 : return gnutls_error_to_ntstatus(rc,
559 : NT_STATUS_HMAC_NOT_SUPPORTED);
560 : }
561 : }
562 :
563 1069727 : rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
564 1069727 : if (rc < 0) {
565 0 : return gnutls_error_to_ntstatus(rc,
566 : NT_STATUS_HMAC_NOT_SUPPORTED);
567 : }
568 1069727 : rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
569 1069727 : if (rc < 0) {
570 0 : return gnutls_error_to_ntstatus(rc,
571 : NT_STATUS_HMAC_NOT_SUPPORTED);
572 : }
573 :
574 3197706 : for (i = 1; i < count; i++) {
575 4027844 : rc = gnutls_hmac(signing_key->hmac_hnd,
576 2127979 : vector[i].iov_base,
577 2127979 : vector[i].iov_len);
578 2127979 : if (rc < 0) {
579 0 : return gnutls_error_to_ntstatus(rc,
580 : NT_STATUS_HMAC_NOT_SUPPORTED);
581 : }
582 : }
583 1069727 : gnutls_hmac_output(signing_key->hmac_hnd, digest);
584 1069727 : memcpy(signature, digest, 16);
585 1069727 : ZERO_ARRAY(digest);
586 1069727 : return NT_STATUS_OK;
587 : }
588 :
589 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
590 : }
591 :
592 1691904 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
593 : struct iovec *vector,
594 : int count)
595 : {
596 : uint16_t sign_algo_id;
597 : uint8_t *hdr;
598 : uint64_t session_id;
599 : uint8_t res[16];
600 : NTSTATUS status;
601 :
602 : /*
603 : * We expect
604 : * - SMB2 HDR
605 : * - SMB2 BODY FIXED
606 : * - (optional) SMB2 BODY DYN
607 : * - (optional) PADDING
608 : */
609 1691904 : SMB_ASSERT(count >= 2);
610 1691904 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
611 1691904 : SMB_ASSERT(count <= 4);
612 :
613 1691904 : hdr = (uint8_t *)vector[0].iov_base;
614 :
615 1691904 : session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
616 1691904 : if (session_id == 0) {
617 : /*
618 : * do not sign messages with a zero session_id.
619 : * See MS-SMB2 3.2.4.1.1
620 : */
621 0 : return NT_STATUS_OK;
622 : }
623 :
624 1691904 : if (!smb2_signing_key_valid(signing_key)) {
625 0 : DBG_WARNING("No signing key for SMB2 signing\n");
626 0 : return NT_STATUS_ACCESS_DENIED;
627 : }
628 :
629 1708723 : memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
630 :
631 1691904 : SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
632 :
633 1691904 : sign_algo_id = signing_key->sign_algo_id;
634 :
635 1691904 : status = smb2_signing_calc_signature(signing_key,
636 : sign_algo_id,
637 : vector,
638 : count,
639 : res);
640 1691904 : if (!NT_STATUS_IS_OK(status)) {
641 0 : DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
642 : (unsigned)sign_algo_id, nt_errstr(status));
643 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
644 0 : smb_panic(__location__);
645 : }
646 0 : return status;
647 : }
648 :
649 1691904 : DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
650 : (unsigned)sign_algo_id));
651 :
652 1708723 : memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
653 :
654 1691904 : return NT_STATUS_OK;
655 : }
656 :
657 1686005 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
658 : const struct iovec *vector,
659 : int count)
660 : {
661 : uint16_t sign_algo_id;
662 : const uint8_t *hdr;
663 : const uint8_t *sig;
664 : uint64_t session_id;
665 : uint8_t res[16];
666 : NTSTATUS status;
667 :
668 : /*
669 : * We expect
670 : * - SMB2 HDR
671 : * - SMB2 BODY FIXED
672 : * - (optional) SMB2 BODY DYN
673 : * - (optional) PADDING
674 : */
675 1686005 : SMB_ASSERT(count >= 2);
676 1686005 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
677 1686005 : SMB_ASSERT(count <= 4);
678 :
679 1686005 : hdr = (const uint8_t *)vector[0].iov_base;
680 :
681 1686005 : session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
682 1686005 : if (session_id == 0) {
683 : /*
684 : * do not sign messages with a zero session_id.
685 : * See MS-SMB2 3.2.4.1.1
686 : */
687 0 : return NT_STATUS_OK;
688 : }
689 :
690 1686005 : if (!smb2_signing_key_valid(signing_key)) {
691 : /* we don't have the session key yet */
692 0 : return NT_STATUS_OK;
693 : }
694 :
695 1686005 : sig = hdr+SMB2_HDR_SIGNATURE;
696 :
697 1686005 : sign_algo_id = signing_key->sign_algo_id;
698 :
699 1686005 : status = smb2_signing_calc_signature(signing_key,
700 : sign_algo_id,
701 : vector,
702 : count,
703 : res);
704 1686005 : if (!NT_STATUS_IS_OK(status)) {
705 0 : DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
706 : (unsigned)sign_algo_id, nt_errstr(status));
707 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
708 0 : status = NT_STATUS_ACCESS_DENIED;
709 : }
710 0 : return status;
711 : }
712 :
713 1686005 : if (memcmp_const_time(res, sig, 16) != 0) {
714 202 : DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
715 : (unsigned)sign_algo_id));
716 202 : dump_data(0, sig, 16);
717 202 : dump_data(0, res, 16);
718 202 : return NT_STATUS_ACCESS_DENIED;
719 : }
720 :
721 1685803 : return NT_STATUS_OK;
722 : }
723 :
724 142308 : NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
725 : const uint8_t *Label, size_t Label_len,
726 : const uint8_t *Context, size_t Context_len,
727 : uint8_t *KO, size_t KO_len)
728 142308 : {
729 142308 : gnutls_hmac_hd_t hmac_hnd = NULL;
730 : uint8_t buf[4];
731 : static const uint8_t zero = 0;
732 142308 : const size_t digest_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256);
733 142308 : uint8_t digest[digest_len];
734 142308 : uint32_t i = 1;
735 142308 : uint32_t L = KO_len * 8;
736 : int rc;
737 :
738 142308 : if (KO_len > digest_len) {
739 0 : DBG_ERR("KO_len[%zu] > digest_len[%zu]\n", KO_len, digest_len);
740 0 : return NT_STATUS_INTERNAL_ERROR;
741 : }
742 :
743 142308 : switch (KO_len) {
744 139200 : case 16:
745 : case 32:
746 139200 : break;
747 0 : default:
748 0 : DBG_ERR("KO_len[%zu] not supported\n", KO_len);
749 0 : return NT_STATUS_INTERNAL_ERROR;
750 : }
751 :
752 : /*
753 : * a simplified version of
754 : * "NIST Special Publication 800-108" section 5.1
755 : * using hmac-sha256.
756 : */
757 142308 : rc = gnutls_hmac_init(&hmac_hnd,
758 : GNUTLS_MAC_SHA256,
759 : KI,
760 : KI_len);
761 142308 : if (rc < 0) {
762 0 : return gnutls_error_to_ntstatus(rc,
763 : NT_STATUS_HMAC_NOT_SUPPORTED);
764 : }
765 :
766 142308 : RSIVAL(buf, 0, i);
767 142308 : rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
768 142308 : if (rc < 0) {
769 0 : return gnutls_error_to_ntstatus(rc,
770 : NT_STATUS_HMAC_NOT_SUPPORTED);
771 : }
772 142308 : rc = gnutls_hmac(hmac_hnd, Label, Label_len);
773 142308 : if (rc < 0) {
774 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
775 0 : return gnutls_error_to_ntstatus(rc,
776 : NT_STATUS_HMAC_NOT_SUPPORTED);
777 : }
778 142308 : rc = gnutls_hmac(hmac_hnd, &zero, 1);
779 142308 : if (rc < 0) {
780 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
781 0 : return gnutls_error_to_ntstatus(rc,
782 : NT_STATUS_HMAC_NOT_SUPPORTED);
783 : }
784 142308 : rc = gnutls_hmac(hmac_hnd, Context, Context_len);
785 142308 : if (rc < 0) {
786 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
787 0 : return gnutls_error_to_ntstatus(rc,
788 : NT_STATUS_HMAC_NOT_SUPPORTED);
789 : }
790 142308 : RSIVAL(buf, 0, L);
791 142308 : rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
792 142308 : if (rc < 0) {
793 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
794 0 : return gnutls_error_to_ntstatus(rc,
795 : NT_STATUS_HMAC_NOT_SUPPORTED);
796 : }
797 :
798 142308 : gnutls_hmac_deinit(hmac_hnd, digest);
799 :
800 145416 : memcpy(KO, digest, KO_len);
801 :
802 142308 : ZERO_ARRAY(digest);
803 :
804 142308 : return NT_STATUS_OK;
805 : }
806 :
807 10095 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
808 : struct iovec *vector,
809 : int count)
810 : {
811 : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
812 1659 : bool use_encryptv2 = false;
813 : #endif
814 : uint16_t cipher_id;
815 : uint8_t *tf;
816 : size_t a_total;
817 : ssize_t m_total;
818 10095 : uint32_t iv_size = 0;
819 10095 : uint32_t key_size = 0;
820 10095 : size_t tag_size = 0;
821 10095 : gnutls_cipher_algorithm_t algo = 0;
822 : gnutls_datum_t key;
823 : gnutls_datum_t iv;
824 : NTSTATUS status;
825 : int rc;
826 :
827 10095 : if (count < 1) {
828 0 : return NT_STATUS_INVALID_PARAMETER;
829 : }
830 :
831 10095 : if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
832 0 : return NT_STATUS_INVALID_PARAMETER;
833 : }
834 :
835 10095 : tf = (uint8_t *)vector[0].iov_base;
836 :
837 10095 : if (!smb2_signing_key_valid(encryption_key)) {
838 0 : DBG_WARNING("No encryption key for SMB2 signing\n");
839 0 : return NT_STATUS_ACCESS_DENIED;
840 : }
841 10095 : cipher_id = encryption_key->cipher_algo_id;
842 :
843 10095 : a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
844 :
845 10095 : m_total = iov_buflen(&vector[1], count-1);
846 10095 : if (m_total == -1) {
847 0 : return NT_STATUS_BUFFER_TOO_SMALL;
848 : }
849 :
850 10095 : SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
851 10095 : SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
852 :
853 10095 : switch (cipher_id) {
854 1116 : case SMB2_ENCRYPTION_AES128_CCM:
855 1116 : algo = GNUTLS_CIPHER_AES_128_CCM;
856 1116 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
857 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
858 318 : use_encryptv2 = true;
859 : #endif
860 1116 : break;
861 8619 : case SMB2_ENCRYPTION_AES128_GCM:
862 8619 : algo = GNUTLS_CIPHER_AES_128_GCM;
863 8619 : iv_size = gnutls_cipher_get_iv_size(algo);
864 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
865 1233 : use_encryptv2 = true;
866 : #endif
867 8619 : break;
868 180 : case SMB2_ENCRYPTION_AES256_CCM:
869 180 : algo = GNUTLS_CIPHER_AES_256_CCM;
870 180 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
871 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
872 54 : use_encryptv2 = true;
873 : #endif
874 180 : break;
875 180 : case SMB2_ENCRYPTION_AES256_GCM:
876 180 : algo = GNUTLS_CIPHER_AES_256_GCM;
877 180 : iv_size = gnutls_cipher_get_iv_size(algo);
878 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
879 54 : use_encryptv2 = true;
880 : #endif
881 180 : break;
882 0 : default:
883 0 : return NT_STATUS_INVALID_PARAMETER;
884 : }
885 :
886 10095 : key_size = gnutls_cipher_get_key_size(algo);
887 10095 : tag_size = gnutls_cipher_get_tag_size(algo);
888 :
889 10095 : if (key_size != encryption_key->blob.length) {
890 0 : return NT_STATUS_INTERNAL_ERROR;
891 : }
892 :
893 10095 : if (tag_size != 16) {
894 0 : return NT_STATUS_INTERNAL_ERROR;
895 : }
896 :
897 10095 : key = (gnutls_datum_t) {
898 10095 : .data = encryption_key->blob.data,
899 : .size = key_size,
900 : };
901 :
902 10095 : iv = (gnutls_datum_t) {
903 10095 : .data = tf + SMB2_TF_NONCE,
904 : .size = iv_size,
905 : };
906 :
907 10095 : if (encryption_key->cipher_hnd == NULL) {
908 5531 : rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
909 : algo,
910 : &key);
911 5531 : if (rc < 0) {
912 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
913 0 : goto out;
914 : }
915 : }
916 :
917 10095 : memset(tf + SMB2_TF_NONCE + iv_size,
918 : 0,
919 10095 : 16 - iv_size);
920 :
921 : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
922 1659 : if (use_encryptv2) {
923 1659 : uint8_t tag[tag_size];
924 : giovec_t auth_iov[1];
925 :
926 1659 : auth_iov[0] = (giovec_t) {
927 1659 : .iov_base = tf + SMB2_TF_NONCE,
928 : .iov_len = a_total,
929 : };
930 :
931 1659 : rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
932 1659 : iv.data,
933 1659 : iv.size,
934 : auth_iov,
935 : 1,
936 1659 : &vector[1],
937 : count - 1,
938 : tag,
939 : &tag_size);
940 1659 : if (rc < 0) {
941 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
942 0 : goto out;
943 : }
944 :
945 1659 : memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
946 : } else
947 : #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
948 : {
949 8436 : size_t ptext_size = m_total;
950 8436 : uint8_t *ptext = NULL;
951 8436 : size_t ctext_size = m_total + tag_size;
952 8436 : uint8_t *ctext = NULL;
953 8436 : size_t len = 0;
954 : int i;
955 8436 : TALLOC_CTX *tmp_ctx = NULL;
956 :
957 : /*
958 : * If we come from python bindings, we don't have a stackframe
959 : * around, so use the NULL context.
960 : *
961 : * This is fine as we make sure we free the memory.
962 : */
963 8436 : if (talloc_stackframe_exists()) {
964 8424 : tmp_ctx = talloc_tos();
965 : }
966 :
967 8436 : ptext = talloc_size(tmp_ctx, ptext_size);
968 8436 : if (ptext == NULL) {
969 0 : status = NT_STATUS_NO_MEMORY;
970 0 : goto out;
971 : }
972 :
973 8436 : ctext = talloc_size(tmp_ctx, ctext_size);
974 8436 : if (ctext == NULL) {
975 0 : TALLOC_FREE(ptext);
976 0 : status = NT_STATUS_NO_MEMORY;
977 0 : goto out;
978 : }
979 :
980 32932 : for (i = 1; i < count; i++) {
981 24496 : if (vector[i].iov_base != NULL) {
982 44048 : memcpy(ptext + len,
983 22024 : vector[i].iov_base,
984 22024 : vector[i].iov_len);
985 : }
986 :
987 24496 : len += vector[i].iov_len;
988 24496 : if (len > ptext_size) {
989 0 : TALLOC_FREE(ptext);
990 0 : TALLOC_FREE(ctext);
991 0 : status = NT_STATUS_INTERNAL_ERROR;
992 0 : goto out;
993 : }
994 : }
995 :
996 16872 : rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
997 8436 : iv.data,
998 8436 : iv.size,
999 8436 : tf + SMB2_TF_NONCE,
1000 : a_total,
1001 : tag_size,
1002 : ptext,
1003 : ptext_size,
1004 : ctext,
1005 : &ctext_size);
1006 8436 : if (rc < 0 || ctext_size != m_total + tag_size) {
1007 0 : TALLOC_FREE(ptext);
1008 0 : TALLOC_FREE(ctext);
1009 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1010 0 : goto out;
1011 : }
1012 :
1013 8436 : len = 0;
1014 32932 : for (i = 1; i < count; i++) {
1015 24496 : if (vector[i].iov_base != NULL) {
1016 44048 : memcpy(vector[i].iov_base,
1017 22024 : ctext + len,
1018 22024 : vector[i].iov_len);
1019 : }
1020 :
1021 24496 : len += vector[i].iov_len;
1022 : }
1023 :
1024 8436 : memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
1025 :
1026 8436 : TALLOC_FREE(ptext);
1027 8436 : TALLOC_FREE(ctext);
1028 : }
1029 :
1030 10095 : DBG_INFO("Encrypted SMB2 message\n");
1031 :
1032 10095 : status = NT_STATUS_OK;
1033 10095 : out:
1034 10095 : return status;
1035 : }
1036 :
1037 10080 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
1038 : struct iovec *vector,
1039 : int count)
1040 : {
1041 : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
1042 1657 : bool use_encryptv2 = false;
1043 : #endif
1044 : uint16_t cipher_id;
1045 : uint8_t *tf;
1046 : uint16_t flags;
1047 : size_t a_total;
1048 : ssize_t m_total;
1049 10080 : uint32_t msg_size = 0;
1050 10080 : uint32_t iv_size = 0;
1051 10080 : uint32_t key_size = 0;
1052 10080 : size_t tag_size = 0;
1053 10080 : gnutls_cipher_algorithm_t algo = 0;
1054 : gnutls_datum_t key;
1055 : gnutls_datum_t iv;
1056 : NTSTATUS status;
1057 : int rc;
1058 :
1059 10080 : if (count < 1) {
1060 0 : return NT_STATUS_INVALID_PARAMETER;
1061 : }
1062 :
1063 10080 : if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
1064 0 : return NT_STATUS_INVALID_PARAMETER;
1065 : }
1066 :
1067 10080 : tf = (uint8_t *)vector[0].iov_base;
1068 :
1069 10080 : if (!smb2_signing_key_valid(decryption_key)) {
1070 0 : DBG_WARNING("No decryption key for SMB2 signing\n");
1071 0 : return NT_STATUS_ACCESS_DENIED;
1072 : }
1073 10080 : cipher_id = decryption_key->cipher_algo_id;
1074 :
1075 10080 : a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
1076 :
1077 10080 : m_total = iov_buflen(&vector[1], count-1);
1078 10080 : if (m_total == -1) {
1079 0 : return NT_STATUS_BUFFER_TOO_SMALL;
1080 : }
1081 :
1082 10080 : flags = SVAL(tf, SMB2_TF_FLAGS);
1083 10080 : msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
1084 :
1085 10080 : if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
1086 0 : return NT_STATUS_ACCESS_DENIED;
1087 : }
1088 :
1089 10080 : if (msg_size != m_total) {
1090 0 : return NT_STATUS_INTERNAL_ERROR;
1091 : }
1092 :
1093 10080 : switch (cipher_id) {
1094 1116 : case SMB2_ENCRYPTION_AES128_CCM:
1095 1116 : algo = GNUTLS_CIPHER_AES_128_CCM;
1096 1116 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
1097 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
1098 318 : use_encryptv2 = true;
1099 : #endif
1100 1116 : break;
1101 8604 : case SMB2_ENCRYPTION_AES128_GCM:
1102 8604 : algo = GNUTLS_CIPHER_AES_128_GCM;
1103 8604 : iv_size = gnutls_cipher_get_iv_size(algo);
1104 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
1105 1231 : use_encryptv2 = true;
1106 : #endif
1107 8604 : break;
1108 180 : case SMB2_ENCRYPTION_AES256_CCM:
1109 180 : algo = GNUTLS_CIPHER_AES_256_CCM;
1110 180 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
1111 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
1112 54 : use_encryptv2 = true;
1113 : #endif
1114 180 : break;
1115 180 : case SMB2_ENCRYPTION_AES256_GCM:
1116 180 : algo = GNUTLS_CIPHER_AES_256_GCM;
1117 180 : iv_size = gnutls_cipher_get_iv_size(algo);
1118 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM
1119 54 : use_encryptv2 = true;
1120 : #endif
1121 180 : break;
1122 0 : default:
1123 0 : return NT_STATUS_INVALID_PARAMETER;
1124 : }
1125 :
1126 10080 : key_size = gnutls_cipher_get_key_size(algo);
1127 10080 : tag_size = gnutls_cipher_get_tag_size(algo);
1128 :
1129 10080 : if (key_size != decryption_key->blob.length) {
1130 0 : return NT_STATUS_INTERNAL_ERROR;
1131 : }
1132 :
1133 10080 : if (tag_size != 16) {
1134 0 : return NT_STATUS_INTERNAL_ERROR;
1135 : }
1136 :
1137 10080 : key = (gnutls_datum_t) {
1138 10080 : .data = decryption_key->blob.data,
1139 : .size = key_size,
1140 : };
1141 :
1142 10080 : iv = (gnutls_datum_t) {
1143 10080 : .data = tf + SMB2_TF_NONCE,
1144 : .size = iv_size,
1145 : };
1146 :
1147 10080 : if (decryption_key->cipher_hnd == NULL) {
1148 1026 : rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
1149 : algo,
1150 : &key);
1151 1026 : if (rc < 0) {
1152 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1153 0 : goto out;
1154 : }
1155 : }
1156 :
1157 : /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */
1158 : #ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2
1159 1657 : if (use_encryptv2) {
1160 : giovec_t auth_iov[1];
1161 :
1162 1657 : auth_iov[0] = (giovec_t) {
1163 1657 : .iov_base = tf + SMB2_TF_NONCE,
1164 : .iov_len = a_total,
1165 : };
1166 :
1167 1657 : rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
1168 1657 : iv.data,
1169 1657 : iv.size,
1170 : auth_iov,
1171 : 1,
1172 1657 : &vector[1],
1173 : count - 1,
1174 1657 : tf + SMB2_TF_SIGNATURE,
1175 : tag_size);
1176 1657 : if (rc < 0) {
1177 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1178 0 : goto out;
1179 : }
1180 : } else
1181 : #endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */
1182 : {
1183 8423 : size_t ctext_size = m_total + tag_size;
1184 8423 : uint8_t *ctext = NULL;
1185 8423 : size_t ptext_size = m_total;
1186 8423 : uint8_t *ptext = NULL;
1187 8423 : size_t len = 0;
1188 : int i;
1189 8423 : TALLOC_CTX *tmp_ctx = NULL;
1190 :
1191 : /*
1192 : * If we come from python bindings, we don't have a stackframe
1193 : * around, so use the NULL context.
1194 : *
1195 : * This is fine as we make sure we free the memory.
1196 : */
1197 8423 : if (talloc_stackframe_exists()) {
1198 8423 : tmp_ctx = talloc_tos();
1199 : }
1200 :
1201 : /* GnuTLS doesn't have a iovec API for decryption yet */
1202 :
1203 8423 : ptext = talloc_size(tmp_ctx, ptext_size);
1204 8423 : if (ptext == NULL) {
1205 0 : status = NT_STATUS_NO_MEMORY;
1206 0 : goto out;
1207 : }
1208 :
1209 8423 : ctext = talloc_size(tmp_ctx, ctext_size);
1210 8423 : if (ctext == NULL) {
1211 0 : TALLOC_FREE(ptext);
1212 0 : status = NT_STATUS_NO_MEMORY;
1213 0 : goto out;
1214 : }
1215 :
1216 :
1217 16846 : for (i = 1; i < count; i++) {
1218 16846 : memcpy(ctext + len,
1219 8423 : vector[i].iov_base,
1220 8423 : vector[i].iov_len);
1221 :
1222 8423 : len += vector[i].iov_len;
1223 : }
1224 8423 : if (len != m_total) {
1225 0 : TALLOC_FREE(ptext);
1226 0 : TALLOC_FREE(ctext);
1227 0 : status = NT_STATUS_INTERNAL_ERROR;
1228 0 : goto out;
1229 : }
1230 :
1231 8423 : memcpy(ctext + len,
1232 8423 : tf + SMB2_TF_SIGNATURE,
1233 : tag_size);
1234 :
1235 : /* This function will verify the tag */
1236 16846 : rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
1237 8423 : iv.data,
1238 8423 : iv.size,
1239 8423 : tf + SMB2_TF_NONCE,
1240 : a_total,
1241 : tag_size,
1242 : ctext,
1243 : ctext_size,
1244 : ptext,
1245 : &ptext_size);
1246 8423 : if (rc < 0 || ptext_size != m_total) {
1247 0 : TALLOC_FREE(ptext);
1248 0 : TALLOC_FREE(ctext);
1249 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1250 0 : goto out;
1251 : }
1252 :
1253 8423 : len = 0;
1254 16846 : for (i = 1; i < count; i++) {
1255 16846 : memcpy(vector[i].iov_base,
1256 8423 : ptext + len,
1257 8423 : vector[i].iov_len);
1258 :
1259 8423 : len += vector[i].iov_len;
1260 : }
1261 :
1262 8423 : TALLOC_FREE(ptext);
1263 8423 : TALLOC_FREE(ctext);
1264 : }
1265 :
1266 10080 : DBG_INFO("Decrypted SMB2 message\n");
1267 :
1268 10080 : status = NT_STATUS_OK;
1269 10080 : out:
1270 10080 : return status;
1271 : }
|