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 48204 : 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 48204 : *ds = (struct smb2_signing_derivations) { .signing = NULL, };
37 :
38 48204 : if (protocol >= PROTOCOL_SMB3_11) {
39 41655 : struct smb2_signing_derivation *d = NULL;
40 :
41 41655 : SMB_ASSERT(preauth_hash.length != 0);
42 :
43 41655 : d = &ds->__signing;
44 41655 : ds->signing = d;
45 41655 : d->label = data_blob_string_const_null("SMBSigningKey");
46 41655 : d->context = preauth_hash;
47 :
48 41655 : d = &ds->__cipher_c2s;
49 41655 : ds->cipher_c2s = d;
50 41655 : d->label = data_blob_string_const_null("SMBC2SCipherKey");
51 41655 : d->context = preauth_hash;
52 :
53 41655 : d = &ds->__cipher_s2c;
54 41655 : ds->cipher_s2c = d;
55 41655 : d->label = data_blob_string_const_null("SMBS2CCipherKey");
56 41655 : d->context = preauth_hash;
57 :
58 41655 : d = &ds->__application;
59 41655 : ds->application = d;
60 41655 : d->label = data_blob_string_const_null("SMBAppKey");
61 41655 : d->context = preauth_hash;
62 :
63 6549 : } 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 48204 : }
87 :
88 322003 : static int smb2_signing_key_destructor(struct smb2_signing_key *key)
89 : {
90 322003 : if (key->hmac_hnd != NULL) {
91 7780 : gnutls_hmac_deinit(key->hmac_hnd, NULL);
92 7780 : key->hmac_hnd = NULL;
93 : }
94 :
95 322003 : if (key->cipher_hnd != NULL) {
96 48564 : gnutls_aead_cipher_deinit(key->cipher_hnd);
97 48564 : key->cipher_hnd = NULL;
98 : }
99 :
100 322003 : return 0;
101 : }
102 :
103 54649 : NTSTATUS smb2_signing_key_copy(TALLOC_CTX *mem_ctx,
104 : const struct smb2_signing_key *src,
105 : struct smb2_signing_key **_dst)
106 : {
107 54649 : struct smb2_signing_key *dst = NULL;
108 :
109 54649 : dst = talloc_zero(mem_ctx, struct smb2_signing_key);
110 54649 : if (dst == NULL) {
111 0 : return NT_STATUS_NO_MEMORY;
112 : }
113 54649 : talloc_set_destructor(dst, smb2_signing_key_destructor);
114 :
115 54649 : dst->sign_algo_id = src->sign_algo_id;
116 54649 : dst->cipher_algo_id = src->cipher_algo_id;
117 :
118 54649 : if (src->blob.length == 0) {
119 0 : *_dst = dst;
120 0 : return NT_STATUS_OK;
121 : }
122 :
123 54649 : dst->blob = data_blob_talloc_zero(dst, src->blob.length);
124 54649 : if (dst->blob.length == 0) {
125 0 : TALLOC_FREE(dst);
126 0 : return NT_STATUS_NO_MEMORY;
127 : }
128 54649 : talloc_keep_secret(dst->blob.data);
129 54649 : memcpy(dst->blob.data, src->blob.data, dst->blob.length);
130 :
131 54649 : *_dst = dst;
132 54649 : return NT_STATUS_OK;
133 : }
134 :
135 297092 : 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 297092 : struct smb2_signing_key *key = NULL;
143 297092 : size_t in_key_length = 16;
144 297092 : size_t out_key_length = 16;
145 7597 : NTSTATUS status;
146 :
147 297092 : if (sign_algo_id != SMB2_SIGNING_INVALID_ALGO) {
148 208003 : SMB_ASSERT(cipher_algo_id == SMB2_ENCRYPTION_INVALID_ALGO);
149 : }
150 297092 : if (cipher_algo_id != SMB2_ENCRYPTION_INVALID_ALGO) {
151 89089 : SMB_ASSERT(sign_algo_id == SMB2_SIGNING_INVALID_ALGO);
152 : }
153 :
154 297092 : key = talloc_zero(mem_ctx, struct smb2_signing_key);
155 297092 : if (key == NULL) {
156 0 : return NT_STATUS_NO_MEMORY;
157 : }
158 297092 : talloc_set_destructor(key, smb2_signing_key_destructor);
159 :
160 297092 : key->sign_algo_id = sign_algo_id;
161 297092 : key->cipher_algo_id = cipher_algo_id;
162 :
163 297092 : if (master_key == NULL) {
164 108114 : SMB_ASSERT(d == NULL);
165 :
166 108114 : *_key = key;
167 108114 : return NT_STATUS_OK;
168 : }
169 :
170 : /*
171 : * Per default use the full key.
172 : */
173 188978 : in_key_length = out_key_length = master_key->length;
174 188978 : switch (sign_algo_id) {
175 85468 : case SMB2_SIGNING_INVALID_ALGO:
176 : /*
177 : * This means we're processing cipher_algo_id below
178 : */
179 85468 : break;
180 5542 : case SMB2_SIGNING_MD5_SMB1:
181 5542 : SMB_ASSERT(d == NULL);
182 5409 : break;
183 95504 : 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 95504 : in_key_length = out_key_length = 16;
194 95504 : 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 188978 : switch (cipher_algo_id) {
200 98399 : case SMB2_ENCRYPTION_INVALID_ALGO:
201 : /*
202 : * This means we're processing sign_algo_id above
203 : */
204 98399 : break;
205 8230 : case SMB2_ENCRYPTION_NONE:
206 : /*
207 : * No encryption negotiated.
208 : */
209 8230 : break;
210 79578 : 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 79578 : 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 77158 : in_key_length = out_key_length = 16;
222 77158 : 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 186542 : if (out_key_length == 0) {
242 0 : *_key = key;
243 0 : return NT_STATUS_OK;
244 : }
245 :
246 188978 : key->blob = data_blob_talloc_zero(key, out_key_length);
247 188978 : if (key->blob.length == 0) {
248 0 : TALLOC_FREE(key);
249 0 : return NT_STATUS_NO_MEMORY;
250 : }
251 188978 : talloc_keep_secret(key->blob.data);
252 188978 : memcpy(key->blob.data,
253 188978 : master_key->data,
254 188978 : MIN(key->blob.length, master_key->length));
255 :
256 188978 : if (d == NULL) {
257 26192 : *_key = key;
258 26192 : return NT_STATUS_OK;
259 : }
260 :
261 162786 : status = samba_gnutls_sp800_108_derive_key(key->blob.data,
262 : in_key_length,
263 : NULL,
264 : 0,
265 162786 : d->label.data,
266 162786 : d->label.length,
267 162786 : d->context.data,
268 162786 : d->context.length,
269 : GNUTLS_MAC_SHA256,
270 : key->blob.data,
271 : out_key_length);
272 162786 : if (!NT_STATUS_IS_OK(status)) {
273 0 : TALLOC_FREE(key);
274 0 : return status;
275 : }
276 :
277 162786 : *_key = key;
278 162786 : return NT_STATUS_OK;
279 : }
280 :
281 208003 : 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 208003 : 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 89089 : 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 89089 : 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 10387766 : bool smb2_signing_key_valid(const struct smb2_signing_key *key)
310 : {
311 10387766 : if (key == NULL) {
312 786523 : return false;
313 : }
314 :
315 9597765 : if (key->blob.length == 0 || key->blob.data == NULL) {
316 281587 : return false;
317 : }
318 :
319 9214928 : return true;
320 : }
321 :
322 2545219 : 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 2545219 : size_t tag_size = _tag_size;
328 36952 : int rc;
329 :
330 2545219 : rc = gnutls_aead_cipher_encryptv2(cipher_hnd,
331 : iv, iv_size,
332 : auth_iov, auth_iovcnt,
333 : NULL, 0,
334 : tag, &tag_size);
335 2545219 : if (rc < 0) {
336 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
337 : }
338 :
339 2545219 : return NT_STATUS_OK;
340 : }
341 :
342 3668291 : 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 3668291 : const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
349 38410 : uint16_t opcode;
350 38410 : uint32_t flags;
351 38410 : uint64_t msg_id;
352 38410 : static const uint8_t zero_sig[16] = { 0, };
353 3668291 : gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
354 38410 : int i;
355 :
356 : /*
357 : * We expect
358 : * - SMB2 HDR
359 : * - SMB2 BODY FIXED
360 : * - (optional) SMB2 BODY DYN
361 : * - (optional) PADDING
362 : */
363 3668291 : SMB_ASSERT(count >= 2);
364 3668291 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
365 3668291 : SMB_ASSERT(count <= 4);
366 :
367 3668291 : opcode = SVAL(hdr, SMB2_HDR_OPCODE);
368 3668291 : flags = IVAL(hdr, SMB2_HDR_FLAGS);
369 3668291 : if (flags & SMB2_HDR_FLAG_REDIRECT) {
370 1853447 : NTSTATUS pdu_status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
371 1853447 : 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 1853447 : 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 3668291 : msg_id = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
381 3668291 : 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 3668291 : 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 3668291 : switch (sign_algo_id) {
399 2545219 : case SMB2_SIGNING_AES128_GMAC: {
400 2545219 : gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_128_GCM;
401 2545219 : uint32_t key_size = gnutls_cipher_get_key_size(algo);
402 2545219 : uint32_t iv_size = gnutls_cipher_get_iv_size(algo);
403 2545219 : size_t tag_size = gnutls_cipher_get_tag_size(algo);
404 2545219 : gnutls_datum_t key = {
405 2545219 : .data = signing_key->blob.data,
406 2545219 : .size = MIN(signing_key->blob.length, key_size),
407 : };
408 2545219 : uint64_t high_bits = 0;
409 2545219 : uint8_t iv[AES_BLOCK_SIZE] = {0};
410 2545219 : giovec_t auth_iov[count+1];
411 2545219 : size_t auth_iovcnt = 0;
412 36952 : NTSTATUS status;
413 36952 : int rc;
414 :
415 2545219 : high_bits = flags & SMB2_HDR_FLAG_REDIRECT;
416 2545219 : if (opcode == SMB2_OP_CANCEL) {
417 38 : high_bits |= SMB2_HDR_FLAG_ASYNC;
418 : }
419 2545219 : SBVAL(iv, 0, msg_id);
420 2545219 : SBVAL(iv, 8, high_bits);
421 :
422 2545219 : if (signing_key->cipher_hnd == NULL) {
423 42547 : rc = gnutls_aead_cipher_init(&signing_key->cipher_hnd,
424 : algo,
425 : &key);
426 42547 : if (rc < 0) {
427 0 : return gnutls_error_to_ntstatus(rc,
428 : NT_STATUS_HMAC_NOT_SUPPORTED);
429 : }
430 : }
431 :
432 2545219 : SMB_ASSERT(key_size == 16);
433 2545219 : SMB_ASSERT(iv_size == 12);
434 2545219 : SMB_ASSERT(tag_size == 16);
435 :
436 2545219 : auth_iov[auth_iovcnt++] = (giovec_t) {
437 : .iov_base = discard_const_p(uint8_t, hdr),
438 : .iov_len = SMB2_HDR_SIGNATURE,
439 : };
440 2545219 : auth_iov[auth_iovcnt++] = (giovec_t) {
441 : .iov_base = discard_const_p(uint8_t, zero_sig),
442 : .iov_len = 16,
443 : };
444 7615257 : for (i=1; i < count; i++) {
445 5070038 : auth_iov[auth_iovcnt++] = (giovec_t) {
446 5070038 : .iov_base = discard_const_p(uint8_t, vector[i].iov_base),
447 5070038 : .iov_len = vector[i].iov_len,
448 : };
449 : }
450 :
451 2545219 : 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 2545219 : if (!NT_STATUS_IS_OK(status)) {
459 0 : return status;
460 : }
461 :
462 2545219 : 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 1119472 : case SMB2_SIGNING_HMAC_SHA256:
469 1119472 : hmac_algo = GNUTLS_MAC_SHA256;
470 1119472 : break;
471 :
472 0 : default:
473 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
474 : }
475 :
476 1123072 : if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
477 1123072 : uint8_t digest[gnutls_hmac_get_len(hmac_algo)];
478 1123072 : gnutls_datum_t key = {
479 1123072 : .data = signing_key->blob.data,
480 1123072 : .size = MIN(signing_key->blob.length, 16),
481 : };
482 1458 : int rc;
483 :
484 1123072 : if (signing_key->hmac_hnd == NULL) {
485 7824 : rc = gnutls_hmac_init(&signing_key->hmac_hnd,
486 : hmac_algo,
487 7544 : key.data,
488 7544 : key.size);
489 7824 : if (rc < 0) {
490 0 : return gnutls_error_to_ntstatus(rc,
491 : NT_STATUS_HMAC_NOT_SUPPORTED);
492 : }
493 : }
494 :
495 1123072 : rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
496 1123072 : if (rc < 0) {
497 0 : return gnutls_error_to_ntstatus(rc,
498 : NT_STATUS_HMAC_NOT_SUPPORTED);
499 : }
500 1123072 : rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
501 1123072 : if (rc < 0) {
502 0 : return gnutls_error_to_ntstatus(rc,
503 : NT_STATUS_HMAC_NOT_SUPPORTED);
504 : }
505 :
506 3356510 : for (i = 1; i < count; i++) {
507 2236350 : rc = gnutls_hmac(signing_key->hmac_hnd,
508 2233438 : vector[i].iov_base,
509 2233438 : vector[i].iov_len);
510 2233438 : if (rc < 0) {
511 0 : return gnutls_error_to_ntstatus(rc,
512 : NT_STATUS_HMAC_NOT_SUPPORTED);
513 : }
514 : }
515 1123072 : gnutls_hmac_output(signing_key->hmac_hnd, digest);
516 1123072 : memcpy(signature, digest, 16);
517 1123072 : ZERO_ARRAY(digest);
518 1123072 : return NT_STATUS_OK;
519 : }
520 :
521 0 : return NT_STATUS_HMAC_NOT_SUPPORTED;
522 : }
523 :
524 1837321 : NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
525 : struct iovec *vector,
526 : int count)
527 : {
528 19541 : uint16_t sign_algo_id;
529 19541 : uint8_t *hdr;
530 19541 : uint64_t session_id;
531 19541 : uint8_t res[16];
532 19541 : NTSTATUS status;
533 :
534 : /*
535 : * We expect
536 : * - SMB2 HDR
537 : * - SMB2 BODY FIXED
538 : * - (optional) SMB2 BODY DYN
539 : * - (optional) PADDING
540 : */
541 1837321 : SMB_ASSERT(count >= 2);
542 1837321 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
543 1837321 : SMB_ASSERT(count <= 4);
544 :
545 1837321 : hdr = (uint8_t *)vector[0].iov_base;
546 :
547 1837321 : session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
548 1837321 : 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 1837321 : 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 1837321 : memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
562 :
563 1837321 : SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
564 :
565 1837321 : sign_algo_id = signing_key->sign_algo_id;
566 :
567 1837321 : status = smb2_signing_calc_signature(signing_key,
568 : sign_algo_id,
569 : vector,
570 : count,
571 : res);
572 1837321 : 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 1837321 : DEBUG(5,("signed SMB2 message (sign_algo_id=%u)\n",
582 : (unsigned)sign_algo_id));
583 :
584 1837321 : memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
585 :
586 1837321 : return NT_STATUS_OK;
587 : }
588 :
589 1830970 : NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
590 : const struct iovec *vector,
591 : int count)
592 : {
593 18869 : uint16_t sign_algo_id;
594 18869 : const uint8_t *hdr;
595 18869 : const uint8_t *sig;
596 18869 : uint64_t session_id;
597 18869 : uint8_t res[16];
598 18869 : NTSTATUS status;
599 :
600 : /*
601 : * We expect
602 : * - SMB2 HDR
603 : * - SMB2 BODY FIXED
604 : * - (optional) SMB2 BODY DYN
605 : * - (optional) PADDING
606 : */
607 1830970 : SMB_ASSERT(count >= 2);
608 1830970 : SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
609 1830970 : SMB_ASSERT(count <= 4);
610 :
611 1830970 : hdr = (const uint8_t *)vector[0].iov_base;
612 :
613 1830970 : session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
614 1830970 : 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 1830970 : 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 1830970 : sig = hdr+SMB2_HDR_SIGNATURE;
628 :
629 1830970 : sign_algo_id = signing_key->sign_algo_id;
630 :
631 1830970 : status = smb2_signing_calc_signature(signing_key,
632 : sign_algo_id,
633 : vector,
634 : count,
635 : res);
636 1830970 : 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 1830970 : 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 1830714 : return NT_STATUS_OK;
654 : }
655 :
656 14678 : NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key,
657 : struct iovec *vector,
658 : int count)
659 : {
660 14678 : 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 14678 : uint32_t iv_size = 0;
666 14678 : uint32_t key_size = 0;
667 14678 : size_t tag_size = 0;
668 14678 : 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 14678 : if (count < 1) {
675 0 : return NT_STATUS_INVALID_PARAMETER;
676 : }
677 :
678 14678 : if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
679 0 : return NT_STATUS_INVALID_PARAMETER;
680 : }
681 :
682 14678 : tf = (uint8_t *)vector[0].iov_base;
683 :
684 14678 : 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 14678 : cipher_id = encryption_key->cipher_algo_id;
689 :
690 14678 : a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
691 :
692 14678 : m_total = iov_buflen(&vector[1], count-1);
693 14678 : if (m_total == -1) {
694 0 : return NT_STATUS_BUFFER_TOO_SMALL;
695 : }
696 :
697 14678 : SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
698 14678 : SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
699 :
700 14678 : 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 12918 : case SMB2_ENCRYPTION_AES128_GCM:
709 12918 : algo = GNUTLS_CIPHER_AES_128_GCM;
710 12918 : iv_size = gnutls_cipher_get_iv_size(algo);
711 12918 : use_encryptv2 = true;
712 12918 : 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 14678 : key_size = gnutls_cipher_get_key_size(algo);
730 14678 : tag_size = gnutls_cipher_get_tag_size(algo);
731 :
732 14678 : if (key_size != encryption_key->blob.length) {
733 0 : return NT_STATUS_INTERNAL_ERROR;
734 : }
735 :
736 14678 : if (tag_size != 16) {
737 0 : return NT_STATUS_INTERNAL_ERROR;
738 : }
739 :
740 14678 : key = (gnutls_datum_t) {
741 14678 : .data = encryption_key->blob.data,
742 : .size = key_size,
743 : };
744 :
745 14678 : iv = (gnutls_datum_t) {
746 14678 : .data = tf + SMB2_TF_NONCE,
747 : .size = iv_size,
748 : };
749 :
750 14678 : if (encryption_key->cipher_hnd == NULL) {
751 7924 : rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd,
752 : algo,
753 : &key);
754 7924 : if (rc < 0) {
755 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
756 0 : goto out;
757 : }
758 : }
759 :
760 14678 : memset(tf + SMB2_TF_NONCE + iv_size,
761 : 0,
762 14678 : 16 - iv_size);
763 :
764 14678 : if (use_encryptv2) {
765 14678 : uint8_t tag[tag_size];
766 990 : giovec_t auth_iov[1];
767 :
768 14678 : auth_iov[0] = (giovec_t) {
769 13688 : .iov_base = tf + SMB2_TF_NONCE,
770 : .iov_len = a_total,
771 : };
772 :
773 14678 : rc = gnutls_aead_cipher_encryptv2(encryption_key->cipher_hnd,
774 13688 : iv.data,
775 13688 : iv.size,
776 : auth_iov,
777 : 1,
778 13688 : &vector[1],
779 : count - 1,
780 : tag,
781 : &tag_size);
782 14678 : if (rc < 0) {
783 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
784 0 : goto out;
785 : }
786 :
787 14678 : 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 14678 : DBG_INFO("Encrypted SMB2 message\n");
872 :
873 13688 : status = NT_STATUS_OK;
874 14678 : out:
875 14678 : return status;
876 : }
877 :
878 14663 : NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key,
879 : struct iovec *vector,
880 : int count)
881 : {
882 14663 : 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 14663 : uint32_t msg_size = 0;
889 14663 : uint32_t iv_size = 0;
890 14663 : uint32_t key_size = 0;
891 14663 : size_t tag_size = 0;
892 14663 : 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 14663 : if (count < 1) {
899 0 : return NT_STATUS_INVALID_PARAMETER;
900 : }
901 :
902 14663 : if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
903 0 : return NT_STATUS_INVALID_PARAMETER;
904 : }
905 :
906 14663 : tf = (uint8_t *)vector[0].iov_base;
907 :
908 14663 : 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 14663 : cipher_id = decryption_key->cipher_algo_id;
913 :
914 14663 : a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
915 :
916 14663 : m_total = iov_buflen(&vector[1], count-1);
917 14663 : if (m_total == -1) {
918 0 : return NT_STATUS_BUFFER_TOO_SMALL;
919 : }
920 :
921 14663 : flags = SVAL(tf, SMB2_TF_FLAGS);
922 14663 : msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
923 :
924 14663 : if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
925 0 : return NT_STATUS_ACCESS_DENIED;
926 : }
927 :
928 14663 : if (msg_size != m_total) {
929 0 : return NT_STATUS_INTERNAL_ERROR;
930 : }
931 :
932 14663 : 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 12903 : case SMB2_ENCRYPTION_AES128_GCM:
941 12903 : algo = GNUTLS_CIPHER_AES_128_GCM;
942 12903 : iv_size = gnutls_cipher_get_iv_size(algo);
943 12903 : use_encryptv2 = true;
944 12903 : 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 14663 : key_size = gnutls_cipher_get_key_size(algo);
962 14663 : tag_size = gnutls_cipher_get_tag_size(algo);
963 :
964 14663 : if (key_size != decryption_key->blob.length) {
965 0 : return NT_STATUS_INTERNAL_ERROR;
966 : }
967 :
968 14663 : if (tag_size != 16) {
969 0 : return NT_STATUS_INTERNAL_ERROR;
970 : }
971 :
972 14663 : key = (gnutls_datum_t) {
973 14663 : .data = decryption_key->blob.data,
974 : .size = key_size,
975 : };
976 :
977 14663 : iv = (gnutls_datum_t) {
978 14663 : .data = tf + SMB2_TF_NONCE,
979 : .size = iv_size,
980 : };
981 :
982 14663 : if (decryption_key->cipher_hnd == NULL) {
983 1345 : rc = gnutls_aead_cipher_init(&decryption_key->cipher_hnd,
984 : algo,
985 : &key);
986 1345 : if (rc < 0) {
987 0 : status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR);
988 0 : goto out;
989 : }
990 : }
991 :
992 14663 : if (use_encryptv2) {
993 990 : giovec_t auth_iov[1];
994 :
995 14663 : auth_iov[0] = (giovec_t) {
996 13673 : .iov_base = tf + SMB2_TF_NONCE,
997 : .iov_len = a_total,
998 : };
999 :
1000 15653 : rc = gnutls_aead_cipher_decryptv2(decryption_key->cipher_hnd,
1001 13673 : iv.data,
1002 13673 : iv.size,
1003 : auth_iov,
1004 : 1,
1005 13673 : &vector[1],
1006 : count - 1,
1007 14663 : tf + SMB2_TF_SIGNATURE,
1008 : tag_size);
1009 14663 : 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 14663 : DBG_INFO("Decrypted SMB2 message\n");
1106 :
1107 13673 : status = NT_STATUS_OK;
1108 14663 : out:
1109 14663 : return status;
1110 : }
|