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