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