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 48463 : 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 48463 : *ds = (struct smb2_signing_derivations) { .signing = NULL, };
37 :
38 48463 : if (protocol >= PROTOCOL_SMB3_11) {
39 41898 : struct smb2_signing_derivation *d = NULL;
40 :
41 41898 : SMB_ASSERT(preauth_hash.length != 0);
42 :
43 41898 : d = &ds->__signing;
44 41898 : ds->signing = d;
45 41898 : d->label = data_blob_string_const_null("SMBSigningKey");
46 41898 : d->context = preauth_hash;
47 :
48 41898 : d = &ds->__cipher_c2s;
49 41898 : ds->cipher_c2s = d;
50 41898 : d->label = data_blob_string_const_null("SMBC2SCipherKey");
51 41898 : d->context = preauth_hash;
52 :
53 41898 : d = &ds->__cipher_s2c;
54 41898 : ds->cipher_s2c = d;
55 41898 : d->label = data_blob_string_const_null("SMBS2CCipherKey");
56 41898 : d->context = preauth_hash;
57 :
58 41898 : d = &ds->__application;
59 41898 : ds->application = d;
60 41898 : d->label = data_blob_string_const_null("SMBAppKey");
61 41898 : d->context = preauth_hash;
62 :
63 6565 : } 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 48463 : }
87 :
88 321784 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
89 : {
90 321784 : if (key->hmac_hnd != NULL) {
91 7790 : gnutls_hmac_deinit(key->hmac_hnd, NULL);
92 7790 : key->hmac_hnd = NULL;
93 : }
94 :
95 321784 : if (key->cipher_hnd != NULL) {
96 48726 : gnutls_aead_cipher_deinit(key->cipher_hnd);
97 48726 : key->cipher_hnd = NULL;
98 : }
99 :
100 321784 : return 0;
101 : }
102 :
103 54952 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
104 : const struct smb2_signing_key *src,
105 : struct smb2_signing_key **_dst)
106 : {
107 54952 : struct smb2_signing_key *dst = NULL;
108 :
109 54952 : dst = talloc_zero(mem_ctx, struct smb2_signing_key);
110 54952 : if (dst == NULL) {
111 0 : return NT_STATUS_NO_MEMORY;
112 : }
113 54952 : talloc_set_destructor(dst, smb2_signing_key_destructor);
114 :
115 54952 : dst->sign_algo_id = src->sign_algo_id;
116 54952 : dst->cipher_algo_id = src->cipher_algo_id;
117 :
118 54952 : if (src->blob.length == 0) {
119 0 : *_dst = dst;
120 0 : return NT_STATUS_OK;
121 : }
122 :
123 54952 : dst->blob = data_blob_talloc_zero(dst, src->blob.length);
124 54952 : if (dst->blob.length == 0) {
125 0 : TALLOC_FREE(dst);
126 0 : return NT_STATUS_NO_MEMORY;
127 : }
128 54952 : talloc_keep_secret(dst->blob.data);
129 54952 : memcpy(dst->blob.data, src->blob.data, dst->blob.length);
130 :
131 54952 : *_dst = dst;
132 54952 : return NT_STATUS_OK;
133 : }
134 :
135 296500 : 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 296500 : struct smb2_signing_key *key = NULL;
143 296500 : size_t in_key_length = 16;
144 296500 : size_t out_key_length = 16;
145 7597 : NTSTATUS status;
146 :
147 296500 : if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
148 207181 : SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
149 : }
150 296500 : if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
151 89319 : SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
152 : }
153 :
154 296500 : key = talloc_zero(mem_ctx, struct smb2_signing_key);
155 296500 : if (key == NULL) {
156 0 : return NT_STATUS_NO_MEMORY;
157 : }
158 296500 : talloc_set_destructor(key, smb2_signing_key_destructor);
159 :
160 296500 : key->sign_algo_id = sign_algo_id;
161 296500 : key->cipher_algo_id = cipher_algo_id;
162 :
163 296500 : if (master_key == NULL) {
164 106622 : SMB_ASSERT(d == NULL);
165 :
166 106622 : *_key = key;
167 106622 : return NT_STATUS_OK;
168 : }
169 :
170 : /*
171 : * Per default use the full key.
172 : */
173 189878 : in_key_length = out_key_length = master_key->length;
174 189878 : switch (sign_algo_id) {
175 85698 : case SMB2_SIGNING_INVALID_ALGO:
176 : /*
177 : * This means we're processing cipher_algo_id below
178 : */
179 85698 : break;
180 5694 : case SMB2_SIGNING_MD5_SMB1:
181 5694 : SMB_ASSERT(d == NULL);
182 5561 : break;
183 96022 : 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 96022 : in_key_length = out_key_length = 16;
194 96022 : 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 189878 : switch (cipher_algo_id) {
200 99069 : case SMB2_ENCRYPTION_INVALID_ALGO:
201 : /*
202 : * This means we're processing sign_algo_id above
203 : */
204 99069 : break;
205 8234 : case SMB2_ENCRYPTION_NONE:
206 : /*
207 : * No encryption negotiated.
208 : */
209 8234 : break;
210 79804 : 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 79804 : 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 77384 : in_key_length = out_key_length = 16;
222 77384 : 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 187442 : if (out_key_length == 0) {
242 0 : *_key = key;
243 0 : return NT_STATUS_OK;
244 : }
245 :
246 189878 : key->blob = data_blob_talloc_zero(key, out_key_length);
247 189878 : if (key->blob.length == 0) {
248 0 : TALLOC_FREE(key);
249 0 : return NT_STATUS_NO_MEMORY;
250 : }
251 189878 : talloc_keep_secret(key->blob.data);
252 189878 : memcpy(key->blob.data,
253 189878 : master_key->data,
254 189878 : MIN(key->blob.length, master_key->length));
255 :
256 189878 : if (d == NULL) {
257 26380 : *_key = key;
258 26380 : return NT_STATUS_OK;
259 : }
260 :
261 163498 : status = samba_gnutls_sp800_108_derive_key(key->blob.data,
262 : in_key_length,
263 : NULL,
264 : 0,
265 163498 : d->label.data,
266 163498 : d->label.length,
267 163498 : d->context.data,
268 163498 : d->context.length,
269 : GNUTLS_MAC_SHA256,
270 : key->blob.data,
271 : out_key_length);
272 163498 : if (!NT_STATUS_IS_OK(status)) {
273 0 : TALLOC_FREE(key);
274 0 : return status;
275 : }
276 :
277 163498 : *_key = key;
278 163498 : return NT_STATUS_OK;
279 : }
280 :
281 207181 : NTSTATUS smb2_signing_key_sign_create(TALLOC_CTX *mem_ctx,
282 : uint16_t sign_algo_id,
283 : const DATA_BLOB *master_key,
284 : const struct smb2_signing_derivation *d,
285 : struct smb2_signing_key **_key)
286 : {
287 207181 : return smb2_signing_key_create(mem_ctx,
288 : sign_algo_id,
289 : SMB2_ENCRYPTION_INVALID_ALGO,
290 : master_key,
291 : d,
292 : _key);
293 : }
294 :
295 89319 : NTSTATUS smb2_signing_key_cipher_create(TALLOC_CTX *mem_ctx,
296 : uint16_t cipher_algo_id,
297 : const DATA_BLOB *master_key,
298 : const struct smb2_signing_derivation *d,
299 : struct smb2_signing_key **_key)
300 : {
301 89319 : return smb2_signing_key_create(mem_ctx,
302 : SMB2_SIGNING_INVALID_ALGO,
303 : cipher_algo_id,
304 : master_key,
305 : d,
306 : _key);
307 : }
308 :
309 10448149 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
310 : {
311 10448149 : if (key == NULL) {
312 792630 : return false;
313 : }
314 :
315 9652041 : if (key->blob.length == 0 || key->blob.data == NULL) {
316 283320 : return false;
317 : }
318 :
319 9266806 : return true;
320 : }
321 :
322 2563429 : static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd,
323 : const uint8_t *iv, size_t iv_size,
324 : const giovec_t *auth_iov, uint8_t auth_iovcnt,
325 : uint8_t *tag, size_t _tag_size)
326 : {
327 2563429 : size_t tag_size = _tag_size;
328 37218 : int rc;
329 :
330 2563429 : rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
331 : iv, iv_size,
332 : auth_iov, auth_iovcnt,
333 : NULL, 0,
334 : tag, &tag_size);
335 2563429 : if (rc < 0) {
336 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
337 : }
338 :
339 2563429 : return NT_STATUS_OK;
340 : }
341 :
342 3688969 : static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
343 : uint16_t sign_algo_id,
344 : const struct iovec *vector,
345 : int count,
346 : uint8_t signature[16])
347 : {
348 3688969 : const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
349 38676 : uint16_t opcode;
350 38676 : uint32_t flags;
351 38676 : uint64_t msg_id;
352 38676 : static const uint8_t zero_sig[16] = { 0, };
353 3688969 : gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
354 38676 : int i;
355 :
356 : /*
357 : * We expect
358 : * - SMB2 HDR
359 : * - SMB2 BODY FIXED
360 : * - (optional) SMB2 BODY DYN
361 : * - (optional) PADDING
362 : */
363 3688969 : SMB_ASSERT(count >= 2);
364 3688969 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
365 3688969 : SMB_ASSERT(count <= 4);
366 :
367 3688969 : opcode = SVAL(hdr, SMB2_HDR_OPCODE);
368 3688969 : flags = IVAL(hdr, SMB2_HDR_FLAGS);
369 3688969 : if (flags & SMB2_HDR_FLAG_REDIRECT) {
370 1863892 : NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
371 1863892 : if (NT_STATUS_EQUAL(pdu_status, NT_STATUS_PENDING)) {
372 0 : DBG_ERR("opcode[%u] NT_STATUS_PENDING\n", opcode);
373 0 : return NT_STATUS_INTERNAL_ERROR;
374 : }
375 1863892 : if (opcode == SMB2_OP_CANCEL) {
376 0 : DBG_ERR("SMB2_OP_CANCEL response should not be signed\n");
377 0 : return NT_STATUS_INTERNAL_ERROR;
378 : }
379 : }
380 3688969 : msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
381 3688969 : if (msg_id == 0) {
382 42 : if (opcode != SMB2_OP_CANCEL ||
383 8 : sign_algo_id >= SMB2_SIGNING_AES128_GMAC)
384 : {
385 0 : DBG_ERR("opcode[%u] msg_id == 0\n", opcode);
386 0 : return NT_STATUS_INTERNAL_ERROR;
387 : }
388 : /*
389 : * Legacy algorithms allow MID 0
390 : * for cancel requests
391 : */
392 : }
393 3688969 : if (msg_id == UINT64_MAX) {
394 0 : DBG_ERR("opcode[%u] msg_id == UINT64_MAX\n", opcode);
395 0 : return NT_STATUS_INTERNAL_ERROR;
396 : }
397 :
398 3688969 : switch (sign_algo_id) {
399 2563429 : case SMB2_SIGNING_AES128_GMAC: {
400 2563429 : gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
401 2563429 : uint32_t key_size = gnutls_cipher_get_key_size(algo);
402 2563429 : uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
403 2563429 : size_t tag_size = gnutls_cipher_get_tag_size(algo);
404 2563429 : gnutls_datum_t key = {
405 2563429 : .data = signing_key->blob.data,
406 2563429 : .size = MIN(signing_key->blob.length, key_size),
407 : };
408 2563429 : uint64_t high_bits = 0;
409 2563429 : uint8_t iv[AES_BLOCK_SIZE] = {0};
410 2563429 : giovec_t auth_iov[count+1];
411 2563429 : size_t auth_iovcnt = 0;
412 37218 : NTSTATUS status;
413 37218 : int rc;
414 :
415 2563429 : high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
416 2563429 : if (opcode == SMB2_OP_CANCEL) {
417 38 : high_bits |= SMB2_HDR_FLAG_ASYNC;
418 : }
419 2563429 : SBVAL(iv, 0, msg_id);
420 2563429 : SBVAL(iv, 8, high_bits);
421 :
422 2563429 : if (signing_key->cipher_hnd == NULL) {
423 42660 : rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
424 : algo,
425 : &key);
426 42660 : if (rc < 0) {
427 0 : return gnutls_error_to_ntstatus(rc,
428 : NT_STATUS_HMAC_NOT_SUPPORTED);
429 : }
430 : }
431 :
432 2563429 : SMB_ASSERT(key_size == 16);
433 2563429 : SMB_ASSERT(iv_size == 12);
434 2563429 : SMB_ASSERT(tag_size == 16);
435 :
436 2563429 : auth_iov[auth_iovcnt++] = (giovec_t) {
437 : .iov_base = discard_const_p(uint8_t, hdr),
438 : .iov_len = SMB2_HDR_SIGNATURE,
439 : };
440 2563429 : auth_iov[auth_iovcnt++] = (giovec_t) {
441 : .iov_base = discard_const_p(uint8_t, zero_sig),
442 : .iov_len = 16,
443 : };
444 7669900 : for (i=1; i < count; i++) {
445 5106471 : auth_iov[auth_iovcnt++] = (giovec_t) {
446 5106471 : .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
447 5106471 : .iov_len = vector[i].iov_len,
448 : };
449 : }
450 :
451 2563429 : status = smb2_signing_gmac(signing_key->cipher_hnd,
452 : iv,
453 : iv_size,
454 : auth_iov,
455 : auth_iovcnt,
456 : signature,
457 : tag_size);
458 2563429 : if (!NT_STATUS_IS_OK(status)) {
459 0 : return status;
460 : }
461 :
462 2563429 : return NT_STATUS_OK;
463 : } break;
464 :
465 2988 : case SMB2_SIGNING_AES128_CMAC:
466 2988 : hmac_algo = GNUTLS_MAC_AES_CMAC_128;
467 2988 : break;
468 1121940 : case SMB2_SIGNING_HMAC_SHA256:
469 1121940 : hmac_algo = GNUTLS_MAC_SHA256;
470 1121940 : break;
471 :
472 0 : default:
473 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
474 : }
475 :
476 1125540 : if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
477 1125540 : uint8_t digest[gnutls_hmac_get_len(hmac_algo)];
478 1125540 : gnutls_datum_t key = {
479 1125540 : .data = signing_key->blob.data,
480 1125540 : .size = MIN(signing_key->blob.length, 16),
481 : };
482 1458 : int rc;
483 :
484 1125540 : if (signing_key->hmac_hnd == NULL) {
485 7832 : rc = gnutls_hmac_init(&signing_key->hmac_hnd,
486 : hmac_algo,
487 7552 : key.data,
488 7552 : key.size);
489 7832 : if (rc < 0) {
490 0 : return gnutls_error_to_ntstatus(rc,
491 : NT_STATUS_HMAC_NOT_SUPPORTED);
492 : }
493 : }
494 :
495 1125540 : rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
496 1125540 : if (rc < 0) {
497 0 : return gnutls_error_to_ntstatus(rc,
498 : NT_STATUS_HMAC_NOT_SUPPORTED);
499 : }
500 1125540 : rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
501 1125540 : if (rc < 0) {
502 0 : return gnutls_error_to_ntstatus(rc,
503 : NT_STATUS_HMAC_NOT_SUPPORTED);
504 : }
505 :
506 3363906 : for (i = 1; i < count; i++) {
507 2241278 : rc = gnutls_hmac(signing_key->hmac_hnd,
508 2238366 : vector[i].iov_base,
509 2238366 : vector[i].iov_len);
510 2238366 : if (rc < 0) {
511 0 : return gnutls_error_to_ntstatus(rc,
512 : NT_STATUS_HMAC_NOT_SUPPORTED);
513 : }
514 : }
515 1125540 : gnutls_hmac_output(signing_key->hmac_hnd, digest);
516 1125540 : memcpy(signature, digest, 16);
517 1125540 : ZERO_ARRAY(digest);
518 1125540 : return NT_STATUS_OK;
519 : }
520 :
521 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
522 : }
523 :
524 1847617 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
525 : struct iovec *vector,
526 : int count)
527 : {
528 19674 : uint16_t sign_algo_id;
529 19674 : uint8_t *hdr;
530 19674 : uint64_t session_id;
531 19674 : uint8_t res[16];
532 19674 : NTSTATUS status;
533 :
534 : /*
535 : * We expect
536 : * - SMB2 HDR
537 : * - SMB2 BODY FIXED
538 : * - (optional) SMB2 BODY DYN
539 : * - (optional) PADDING
540 : */
541 1847617 : SMB_ASSERT(count >= 2);
542 1847617 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
543 1847617 : SMB_ASSERT(count <= 4);
544 :
545 1847617 : hdr = (uint8_t *)vector[0].iov_base;
546 :
547 1847617 : session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
548 1847617 : if (session_id == 0) {
549 : /*
550 : * do not sign messages with a zero session_id.
551 : * See MS-SMB2 3.2.4.1.1
552 : */
553 0 : return NT_STATUS_OK;
554 : }
555 :
556 1847617 : if (!smb2_signing_key_valid(signing_key)) {
557 0 : DBG_WARNING("No signing key for SMB2 signing\n");
558 0 : return NT_STATUS_ACCESS_DENIED;
559 : }
560 :
561 1847617 : memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
562 :
563 1847617 : SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
564 :
565 1847617 : sign_algo_id = signing_key->sign_algo_id;
566 :
567 1847617 : status = smb2_signing_calc_signature(signing_key,
568 : sign_algo_id,
569 : vector,
570 : count,
571 : res);
572 1847617 : if (!NT_STATUS_IS_OK(status)) {
573 0 : DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
574 : (unsigned)sign_algo_id, nt_errstr(status));
575 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
576 0 : smb_panic(__location__);
577 : }
578 0 : return status;
579 : }
580 :
581 1847617 : DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
582 : (unsigned)sign_algo_id));
583 :
584 1847617 : memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
585 :
586 1847617 : return NT_STATUS_OK;
587 : }
588 :
589 1841352 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
590 : const struct iovec *vector,
591 : int count)
592 : {
593 19002 : uint16_t sign_algo_id;
594 19002 : const uint8_t *hdr;
595 19002 : const uint8_t *sig;
596 19002 : uint64_t session_id;
597 19002 : uint8_t res[16];
598 19002 : NTSTATUS status;
599 :
600 : /*
601 : * We expect
602 : * - SMB2 HDR
603 : * - SMB2 BODY FIXED
604 : * - (optional) SMB2 BODY DYN
605 : * - (optional) PADDING
606 : */
607 1841352 : SMB_ASSERT(count >= 2);
608 1841352 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
609 1841352 : SMB_ASSERT(count <= 4);
610 :
611 1841352 : hdr = (const uint8_t *)vector[0].iov_base;
612 :
613 1841352 : session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
614 1841352 : if (session_id == 0) {
615 : /*
616 : * do not sign messages with a zero session_id.
617 : * See MS-SMB2 3.2.4.1.1
618 : */
619 0 : return NT_STATUS_OK;
620 : }
621 :
622 1841352 : if (!smb2_signing_key_valid(signing_key)) {
623 : /* we don't have the session key yet */
624 0 : return NT_STATUS_OK;
625 : }
626 :
627 1841352 : sig = hdr+SMB2_HDR_SIGNATURE;
628 :
629 1841352 : sign_algo_id = signing_key->sign_algo_id;
630 :
631 1841352 : status = smb2_signing_calc_signature(signing_key,
632 : sign_algo_id,
633 : vector,
634 : count,
635 : res);
636 1841352 : if (!NT_STATUS_IS_OK(status)) {
637 0 : DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
638 : (unsigned)sign_algo_id, nt_errstr(status));
639 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
640 0 : status = NT_STATUS_ACCESS_DENIED;
641 : }
642 0 : return status;
643 : }
644 :
645 1841352 : if (!mem_equal_const_time(res, sig, 16)) {
646 256 : DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
647 : (unsigned)sign_algo_id));
648 256 : dump_data(0, sig, 16);
649 256 : dump_data(0, res, 16);
650 256 : return NT_STATUS_ACCESS_DENIED;
651 : }
652 :
653 1841096 : return NT_STATUS_OK;
654 : }
655 :
656 14767 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
657 : struct iovec *vector,
658 : int count)
659 : {
660 14767 : bool use_encryptv2 = false;
661 990 : uint16_t cipher_id;
662 990 : uint8_t *tf;
663 990 : size_t a_total;
664 990 : ssize_t m_total;
665 14767 : uint32_t iv_size = 0;
666 14767 : uint32_t key_size = 0;
667 14767 : size_t tag_size = 0;
668 14767 : gnutls_cipher_algorithm_t algo = 0;
669 990 : gnutls_datum_t key;
670 990 : gnutls_datum_t iv;
671 990 : NTSTATUS status;
672 990 : int rc;
673 :
674 14767 : if (count < 1) {
675 0 : return NT_STATUS_INVALID_PARAMETER;
676 : }
677 :
678 14767 : if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
679 0 : return NT_STATUS_INVALID_PARAMETER;
680 : }
681 :
682 14767 : tf = (uint8_t *)vector[0].iov_base;
683 :
684 14767 : if (!smb2_signing_key_valid(encryption_key)) {
685 0 : DBG_WARNING("No encryption key for SMB2 signing\n");
686 0 : return NT_STATUS_ACCESS_DENIED;
687 : }
688 14767 : cipher_id = encryption_key->cipher_algo_id;
689 :
690 14767 : a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
691 :
692 14767 : m_total = iov_buflen(&vector[1], count-1);
693 14767 : if (m_total == -1) {
694 0 : return NT_STATUS_BUFFER_TOO_SMALL;
695 : }
696 :
697 14767 : SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
698 14767 : SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
699 :
700 14767 : switch (cipher_id) {
701 1116 : case SMB2_ENCRYPTION_AES128_CCM:
702 1116 : algo = GNUTLS_CIPHER_AES_128_CCM;
703 1116 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
704 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
705 1116 : use_encryptv2 = true;
706 : #endif
707 1116 : break;
708 13007 : case SMB2_ENCRYPTION_AES128_GCM:
709 13007 : algo = GNUTLS_CIPHER_AES_128_GCM;
710 13007 : iv_size = gnutls_cipher_get_iv_size(algo);
711 13007 : use_encryptv2 = true;
712 13007 : break;
713 216 : case SMB2_ENCRYPTION_AES256_CCM:
714 216 : algo = GNUTLS_CIPHER_AES_256_CCM;
715 216 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
716 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
717 216 : use_encryptv2 = true;
718 : #endif
719 216 : break;
720 216 : case SMB2_ENCRYPTION_AES256_GCM:
721 216 : algo = GNUTLS_CIPHER_AES_256_GCM;
722 216 : iv_size = gnutls_cipher_get_iv_size(algo);
723 216 : use_encryptv2 = true;
724 216 : break;
725 0 : default:
726 0 : return NT_STATUS_INVALID_PARAMETER;
727 : }
728 :
729 14767 : key_size = gnutls_cipher_get_key_size(algo);
730 14767 : tag_size = gnutls_cipher_get_tag_size(algo);
731 :
732 14767 : if (key_size != encryption_key->blob.length) {
733 0 : return NT_STATUS_INTERNAL_ERROR;
734 : }
735 :
736 14767 : if (tag_size != 16) {
737 0 : return NT_STATUS_INTERNAL_ERROR;
738 : }
739 :
740 14767 : key = (gnutls_datum_t) {
741 14767 : .data = encryption_key->blob.data,
742 : .size = key_size,
743 : };
744 :
745 14767 : iv = (gnutls_datum_t) {
746 14767 : .data = tf + SMB2_TF_NONCE,
747 : .size = iv_size,
748 : };
749 :
750 14767 : if (encryption_key->cipher_hnd == NULL) {
751 7967 : rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
752 : algo,
753 : &key);
754 7967 : if (rc < 0) {
755 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
756 0 : goto out;
757 : }
758 : }
759 :
760 14767 : memset(tf + SMB2_TF_NONCE + iv_size,
761 : 0,
762 14767 : 16 - iv_size);
763 :
764 14767 : if (use_encryptv2) {
765 14767 : uint8_t tag[tag_size];
766 990 : giovec_t auth_iov[1];
767 :
768 14767 : auth_iov[0] = (giovec_t) {
769 13777 : .iov_base = tf + SMB2_TF_NONCE,
770 : .iov_len = a_total,
771 : };
772 :
773 14767 : rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
774 13777 : iv.data,
775 13777 : iv.size,
776 : auth_iov,
777 : 1,
778 13777 : &vector[1],
779 : count - 1,
780 : tag,
781 : &tag_size);
782 14767 : if (rc < 0) {
783 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
784 0 : goto out;
785 : }
786 :
787 14767 : memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size);
788 : } else
789 : {
790 0 : size_t ptext_size = m_total;
791 0 : uint8_t *ptext = NULL;
792 0 : size_t ctext_size = m_total + tag_size;
793 0 : uint8_t *ctext = NULL;
794 0 : size_t len = 0;
795 : int i;
796 0 : TALLOC_CTX *tmp_ctx = NULL;
797 :
798 : /*
799 : * If we come from python bindings, we don't have a stackframe
800 : * around, so use the NULL context.
801 : *
802 : * This is fine as we make sure we free the memory.
803 : */
804 0 : if (talloc_stackframe_exists()) {
805 0 : tmp_ctx = talloc_tos();
806 : }
807 :
808 0 : ptext = talloc_size(tmp_ctx, ptext_size);
809 0 : if (ptext == NULL) {
810 0 : status = NT_STATUS_NO_MEMORY;
811 0 : goto out;
812 : }
813 :
814 0 : ctext = talloc_size(tmp_ctx, ctext_size);
815 0 : if (ctext == NULL) {
816 0 : TALLOC_FREE(ptext);
817 0 : status = NT_STATUS_NO_MEMORY;
818 0 : goto out;
819 : }
820 :
821 0 : for (i = 1; i < count; i++) {
822 0 : if (vector[i].iov_base != NULL) {
823 0 : memcpy(ptext + len,
824 0 : vector[i].iov_base,
825 0 : vector[i].iov_len);
826 : }
827 :
828 0 : len += vector[i].iov_len;
829 0 : if (len > ptext_size) {
830 0 : TALLOC_FREE(ptext);
831 0 : TALLOC_FREE(ctext);
832 0 : status = NT_STATUS_INTERNAL_ERROR;
833 0 : goto out;
834 : }
835 : }
836 :
837 0 : rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd,
838 0 : iv.data,
839 0 : iv.size,
840 0 : tf + SMB2_TF_NONCE,
841 : a_total,
842 : tag_size,
843 : ptext,
844 : ptext_size,
845 : ctext,
846 : &ctext_size);
847 0 : if (rc < 0 || ctext_size != m_total + tag_size) {
848 0 : TALLOC_FREE(ptext);
849 0 : TALLOC_FREE(ctext);
850 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
851 0 : goto out;
852 : }
853 :
854 0 : len = 0;
855 0 : for (i = 1; i < count; i++) {
856 0 : if (vector[i].iov_base != NULL) {
857 0 : memcpy(vector[i].iov_base,
858 0 : ctext + len,
859 0 : vector[i].iov_len);
860 : }
861 :
862 0 : len += vector[i].iov_len;
863 : }
864 :
865 0 : memcpy(tf + SMB2_TF_SIGNATURE, ctext + m_total, tag_size);
866 :
867 0 : TALLOC_FREE(ptext);
868 0 : TALLOC_FREE(ctext);
869 : }
870 :
871 14767 : DBG_INFO("Encrypted SMB2 message\n");
872 :
873 13777 : status = NT_STATUS_OK;
874 14767 : out:
875 14767 : return status;
876 : }
877 :
878 14752 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
879 : struct iovec *vector,
880 : int count)
881 : {
882 14752 : bool use_encryptv2 = false;
883 990 : uint16_t cipher_id;
884 990 : uint8_t *tf;
885 990 : uint16_t flags;
886 990 : size_t a_total;
887 990 : ssize_t m_total;
888 14752 : uint32_t msg_size = 0;
889 14752 : uint32_t iv_size = 0;
890 14752 : uint32_t key_size = 0;
891 14752 : size_t tag_size = 0;
892 14752 : gnutls_cipher_algorithm_t algo = 0;
893 990 : gnutls_datum_t key;
894 990 : gnutls_datum_t iv;
895 990 : NTSTATUS status;
896 990 : int rc;
897 :
898 14752 : if (count < 1) {
899 0 : return NT_STATUS_INVALID_PARAMETER;
900 : }
901 :
902 14752 : if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
903 0 : return NT_STATUS_INVALID_PARAMETER;
904 : }
905 :
906 14752 : tf = (uint8_t *)vector[0].iov_base;
907 :
908 14752 : if (!smb2_signing_key_valid(decryption_key)) {
909 0 : DBG_WARNING("No decryption key for SMB2 signing\n");
910 0 : return NT_STATUS_ACCESS_DENIED;
911 : }
912 14752 : cipher_id = decryption_key->cipher_algo_id;
913 :
914 14752 : a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
915 :
916 14752 : m_total = iov_buflen(&vector[1], count-1);
917 14752 : if (m_total == -1) {
918 0 : return NT_STATUS_BUFFER_TOO_SMALL;
919 : }
920 :
921 14752 : flags = SVAL(tf, SMB2_TF_FLAGS);
922 14752 : msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
923 :
924 14752 : if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
925 0 : return NT_STATUS_ACCESS_DENIED;
926 : }
927 :
928 14752 : if (msg_size != m_total) {
929 0 : return NT_STATUS_INTERNAL_ERROR;
930 : }
931 :
932 14752 : switch (cipher_id) {
933 1116 : case SMB2_ENCRYPTION_AES128_CCM:
934 1116 : algo = GNUTLS_CIPHER_AES_128_CCM;
935 1116 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
936 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
937 1116 : use_encryptv2 = true;
938 : #endif
939 1116 : break;
940 12992 : case SMB2_ENCRYPTION_AES128_GCM:
941 12992 : algo = GNUTLS_CIPHER_AES_128_GCM;
942 12992 : iv_size = gnutls_cipher_get_iv_size(algo);
943 12992 : use_encryptv2 = true;
944 12992 : break;
945 216 : case SMB2_ENCRYPTION_AES256_CCM:
946 216 : algo = GNUTLS_CIPHER_AES_256_CCM;
947 216 : iv_size = SMB2_AES_128_CCM_NONCE_SIZE;
948 : #ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM
949 216 : use_encryptv2 = true;
950 : #endif
951 216 : break;
952 216 : case SMB2_ENCRYPTION_AES256_GCM:
953 216 : algo = GNUTLS_CIPHER_AES_256_GCM;
954 216 : iv_size = gnutls_cipher_get_iv_size(algo);
955 216 : use_encryptv2 = true;
956 216 : break;
957 0 : default:
958 0 : return NT_STATUS_INVALID_PARAMETER;
959 : }
960 :
961 14752 : key_size = gnutls_cipher_get_key_size(algo);
962 14752 : tag_size = gnutls_cipher_get_tag_size(algo);
963 :
964 14752 : if (key_size != decryption_key->blob.length) {
965 0 : return NT_STATUS_INTERNAL_ERROR;
966 : }
967 :
968 14752 : if (tag_size != 16) {
969 0 : return NT_STATUS_INTERNAL_ERROR;
970 : }
971 :
972 14752 : key = (gnutls_datum_t) {
973 14752 : .data = decryption_key->blob.data,
974 : .size = key_size,
975 : };
976 :
977 14752 : iv = (gnutls_datum_t) {
978 14752 : .data = tf + SMB2_TF_NONCE,
979 : .size = iv_size,
980 : };
981 :
982 14752 : if (decryption_key->cipher_hnd == NULL) {
983 1343 : rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
984 : algo,
985 : &key);
986 1343 : if (rc < 0) {
987 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
988 0 : goto out;
989 : }
990 : }
991 :
992 14752 : if (use_encryptv2) {
993 990 : giovec_t auth_iov[1];
994 :
995 14752 : auth_iov[0] = (giovec_t) {
996 13762 : .iov_base = tf + SMB2_TF_NONCE,
997 : .iov_len = a_total,
998 : };
999 :
1000 15742 : rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
1001 13762 : iv.data,
1002 13762 : iv.size,
1003 : auth_iov,
1004 : 1,
1005 13762 : &vector[1],
1006 : count - 1,
1007 14752 : tf + SMB2_TF_SIGNATURE,
1008 : tag_size);
1009 14752 : if (rc < 0) {
1010 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1011 0 : goto out;
1012 : }
1013 : } else
1014 : {
1015 0 : size_t ctext_size = m_total + tag_size;
1016 0 : uint8_t *ctext = NULL;
1017 0 : size_t ptext_size = m_total;
1018 0 : uint8_t *ptext = NULL;
1019 0 : size_t len = 0;
1020 : int i;
1021 0 : TALLOC_CTX *tmp_ctx = NULL;
1022 :
1023 : /*
1024 : * If we come from python bindings, we don't have a stackframe
1025 : * around, so use the NULL context.
1026 : *
1027 : * This is fine as we make sure we free the memory.
1028 : */
1029 0 : if (talloc_stackframe_exists()) {
1030 0 : tmp_ctx = talloc_tos();
1031 : }
1032 :
1033 : /* GnuTLS doesn't have a iovec API for decryption yet */
1034 :
1035 0 : ptext = talloc_size(tmp_ctx, ptext_size);
1036 0 : if (ptext == NULL) {
1037 0 : status = NT_STATUS_NO_MEMORY;
1038 0 : goto out;
1039 : }
1040 :
1041 0 : ctext = talloc_size(tmp_ctx, ctext_size);
1042 0 : if (ctext == NULL) {
1043 0 : TALLOC_FREE(ptext);
1044 0 : status = NT_STATUS_NO_MEMORY;
1045 0 : goto out;
1046 : }
1047 :
1048 :
1049 0 : for (i = 1; i < count; i++) {
1050 0 : memcpy(ctext + len,
1051 0 : vector[i].iov_base,
1052 0 : vector[i].iov_len);
1053 :
1054 0 : len += vector[i].iov_len;
1055 : }
1056 0 : if (len != m_total) {
1057 0 : TALLOC_FREE(ptext);
1058 0 : TALLOC_FREE(ctext);
1059 0 : status = NT_STATUS_INTERNAL_ERROR;
1060 0 : goto out;
1061 : }
1062 :
1063 0 : memcpy(ctext + len,
1064 0 : tf + SMB2_TF_SIGNATURE,
1065 : tag_size);
1066 :
1067 : /* This function will verify the tag */
1068 0 : rc = gnutls_aead_cipher_decrypt(decryption_key->cipher_hnd,
1069 0 : iv.data,
1070 0 : iv.size,
1071 0 : tf + SMB2_TF_NONCE,
1072 : a_total,
1073 : tag_size,
1074 : ctext,
1075 : ctext_size,
1076 : ptext,
1077 : &ptext_size);
1078 0 : if (rc < 0) {
1079 0 : TALLOC_FREE(ptext);
1080 0 : TALLOC_FREE(ctext);
1081 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1082 0 : goto out;
1083 : }
1084 0 : if (ptext_size != m_total) {
1085 0 : TALLOC_FREE(ptext);
1086 0 : TALLOC_FREE(ctext);
1087 0 : rc = GNUTLS_E_SHORT_MEMORY_BUFFER;
1088 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
1089 0 : goto out;
1090 : }
1091 :
1092 0 : len = 0;
1093 0 : for (i = 1; i < count; i++) {
1094 0 : memcpy(vector[i].iov_base,
1095 0 : ptext + len,
1096 0 : vector[i].iov_len);
1097 :
1098 0 : len += vector[i].iov_len;
1099 : }
1100 :
1101 0 : TALLOC_FREE(ptext);
1102 0 : TALLOC_FREE(ctext);
1103 : }
1104 :
1105 14752 : DBG_INFO("Decrypted SMB2 message\n");
1106 :
1107 13762 : status = NT_STATUS_OK;
1108 14752 : out:
1109 14752 : return status;
1110 : }
|