01027d55fbeddf5a7fb1be034bb257bdb4646fe0
[metze/samba/wip.git] / libcli / smb / smb2_signing.c
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 "../libcli/smb/smb_common.h"
24 #include "../lib/crypto/crypto.h"
25 #include "lib/util/iov_buf.h"
26
27 #include "lib/crypto/gnutls_helpers.h"
28 #include <gnutls/gnutls.h>
29 #include <gnutls/crypto.h>
30
31 int smb2_signing_key_destructor(struct smb2_signing_key *key)
32 {
33         if (key->hmac_hnd != NULL) {
34                 gnutls_hmac_deinit(key->hmac_hnd, NULL);
35                 key->hmac_hnd = NULL;
36         }
37
38         if (key->cipher_hnd != NULL) {
39                 gnutls_aead_cipher_deinit(key->cipher_hnd);
40                 key->cipher_hnd = NULL;
41         }
42
43         return 0;
44 }
45
46 bool smb2_signing_key_valid(const struct smb2_signing_key *key)
47 {
48         if (key == NULL) {
49                 return false;
50         }
51
52         if (key->blob.length == 0 || key->blob.data == NULL) {
53                 return false;
54         }
55
56         return true;
57 }
58
59 NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
60                                enum protocol_types protocol,
61                                struct iovec *vector,
62                                int count)
63 {
64         uint8_t *hdr;
65         uint64_t session_id;
66         uint8_t res[16];
67         int i;
68
69         if (count < 2) {
70                 return NT_STATUS_INVALID_PARAMETER;
71         }
72
73         if (vector[0].iov_len != SMB2_HDR_BODY) {
74                 return NT_STATUS_INVALID_PARAMETER;
75         }
76
77         hdr = (uint8_t *)vector[0].iov_base;
78
79         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
80         if (session_id == 0) {
81                 /*
82                  * do not sign messages with a zero session_id.
83                  * See MS-SMB2 3.2.4.1.1
84                  */
85                 return NT_STATUS_OK;
86         }
87
88         if (!smb2_signing_key_valid(signing_key)) {
89                 DBG_WARNING("Wrong session key length %zu for SMB2 signing\n",
90                             signing_key->blob.length);
91                 return NT_STATUS_ACCESS_DENIED;
92         }
93
94         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
95
96         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
97
98         if (protocol >= PROTOCOL_SMB2_24) {
99                 struct aes_cmac_128_context ctx;
100                 uint8_t key[AES_BLOCK_SIZE] = {0};
101
102                 memcpy(key,
103                        signing_key->blob.data,
104                        MIN(signing_key->blob.length, 16));
105
106                 aes_cmac_128_init(&ctx, key);
107                 for (i=0; i < count; i++) {
108                         aes_cmac_128_update(&ctx,
109                                         (const uint8_t *)vector[i].iov_base,
110                                         vector[i].iov_len);
111                 }
112                 aes_cmac_128_final(&ctx, res);
113
114                 ZERO_ARRAY(key);
115         } else {
116                 uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
117                 int rc;
118
119                 if (signing_key->hmac_hnd == NULL) {
120                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
121                                               GNUTLS_MAC_SHA256,
122                                               signing_key->blob.data,
123                                               MIN(signing_key->blob.length, 16));
124                         if (rc < 0) {
125                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
126                         }
127                 }
128
129                 for (i = 0; i < count; i++) {
130                         rc = gnutls_hmac(signing_key->hmac_hnd,
131                                          vector[i].iov_base,
132                                          vector[i].iov_len);
133                         if (rc < 0) {
134                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
135                         }
136                 }
137                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
138                 memcpy(res, digest, sizeof(res));
139         }
140         DEBUG(5,("signed SMB2 message\n"));
141
142         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
143
144         return NT_STATUS_OK;
145 }
146
147 NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
148                                 enum protocol_types protocol,
149                                 const struct iovec *vector,
150                                 int count)
151 {
152         const uint8_t *hdr;
153         const uint8_t *sig;
154         uint64_t session_id;
155         uint8_t res[16];
156         static const uint8_t zero_sig[16] = { 0, };
157         int i;
158
159         if (count < 2) {
160                 return NT_STATUS_INVALID_PARAMETER;
161         }
162
163         if (vector[0].iov_len != SMB2_HDR_BODY) {
164                 return NT_STATUS_INVALID_PARAMETER;
165         }
166
167         hdr = (const uint8_t *)vector[0].iov_base;
168
169         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
170         if (session_id == 0) {
171                 /*
172                  * do not sign messages with a zero session_id.
173                  * See MS-SMB2 3.2.4.1.1
174                  */
175                 return NT_STATUS_OK;
176         }
177
178         if (!smb2_signing_key_valid(signing_key)) {
179                 /* we don't have the session key yet */
180                 return NT_STATUS_OK;
181         }
182
183         sig = hdr+SMB2_HDR_SIGNATURE;
184
185         if (protocol >= PROTOCOL_SMB2_24) {
186                 struct aes_cmac_128_context ctx;
187                 uint8_t key[AES_BLOCK_SIZE] = {0};
188
189                 memcpy(key,
190                        signing_key->blob.data,
191                        MIN(signing_key->blob.length, 16));
192
193                 aes_cmac_128_init(&ctx, key);
194                 aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
195                 aes_cmac_128_update(&ctx, zero_sig, 16);
196                 for (i=1; i < count; i++) {
197                         aes_cmac_128_update(&ctx,
198                                         (const uint8_t *)vector[i].iov_base,
199                                         vector[i].iov_len);
200                 }
201                 aes_cmac_128_final(&ctx, res);
202
203                 ZERO_ARRAY(key);
204         } else {
205                 uint8_t digest[gnutls_hash_get_len(GNUTLS_MAC_SHA256)];
206                 int rc;
207
208                 if (signing_key->hmac_hnd == NULL) {
209                         rc = gnutls_hmac_init(&signing_key->hmac_hnd,
210                                               GNUTLS_MAC_SHA256,
211                                               signing_key->blob.data,
212                                               MIN(signing_key->blob.length, 16));
213                         if (rc < 0) {
214                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
215                         }
216                 }
217
218                 rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
219                 if (rc < 0) {
220                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
221                 }
222                 rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
223                 if (rc < 0) {
224                         return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
225                 }
226
227                 for (i = 1; i < count; i++) {
228                         rc = gnutls_hmac(signing_key->hmac_hnd,
229                                          vector[i].iov_base,
230                                          vector[i].iov_len);
231                         if (rc < 0) {
232                                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
233                         }
234                 }
235                 gnutls_hmac_output(signing_key->hmac_hnd, digest);
236                 memcpy(res, digest, 16);
237                 ZERO_ARRAY(digest);
238         }
239
240         if (memcmp_const_time(res, sig, 16) != 0) {
241                 DEBUG(0,("Bad SMB2 signature for message\n"));
242                 dump_data(0, sig, 16);
243                 dump_data(0, res, 16);
244                 return NT_STATUS_ACCESS_DENIED;
245         }
246
247         return NT_STATUS_OK;
248 }
249
250 NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len,
251                              const uint8_t *Label, size_t Label_len,
252                              const uint8_t *Context, size_t Context_len,
253                              uint8_t KO[16])
254 {
255         gnutls_hmac_hd_t hmac_hnd = NULL;
256         uint8_t buf[4];
257         static const uint8_t zero = 0;
258         uint8_t digest[gnutls_hash_get_len(GNUTLS_MAC_SHA256)];
259         uint32_t i = 1;
260         uint32_t L = 128;
261         int rc;
262
263         /*
264          * a simplified version of
265          * "NIST Special Publication 800-108" section 5.1
266          * using hmac-sha256.
267          */
268         rc = gnutls_hmac_init(&hmac_hnd,
269                               GNUTLS_MAC_SHA256,
270                               KI,
271                               KI_len);
272         if (rc < 0) {
273                 return gnutls_error_to_ntstatus(rc,
274                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
275         }
276
277         RSIVAL(buf, 0, i);
278         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
279         if (rc < 0) {
280                 return gnutls_error_to_ntstatus(rc,
281                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
282         }
283         rc = gnutls_hmac(hmac_hnd, Label, Label_len);
284         if (rc < 0) {
285                 gnutls_hmac_deinit(hmac_hnd, NULL);
286                 return gnutls_error_to_ntstatus(rc,
287                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
288         }
289         rc = gnutls_hmac(hmac_hnd, &zero, 1);
290         if (rc < 0) {
291                 gnutls_hmac_deinit(hmac_hnd, NULL);
292                 return gnutls_error_to_ntstatus(rc,
293                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
294         }
295         rc = gnutls_hmac(hmac_hnd, Context, Context_len);
296         if (rc < 0) {
297                 gnutls_hmac_deinit(hmac_hnd, NULL);
298                 return gnutls_error_to_ntstatus(rc,
299                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
300         }
301         RSIVAL(buf, 0, L);
302         rc = gnutls_hmac(hmac_hnd, buf, sizeof(buf));
303         if (rc < 0) {
304                 gnutls_hmac_deinit(hmac_hnd, NULL);
305                 return gnutls_error_to_ntstatus(rc,
306                                                 NT_STATUS_HMAC_NOT_SUPPORTED);
307         }
308
309         gnutls_hmac_deinit(hmac_hnd, digest);
310
311         memcpy(KO, digest, 16);
312
313         ZERO_ARRAY(digest);
314
315         return NT_STATUS_OK;
316 }
317
318 NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key,
319                                   uint16_t cipher_id,
320                                   struct iovec *vector,
321                                   int count)
322 {
323         uint8_t *tf;
324         uint8_t sig[16];
325         int i;
326         size_t a_total;
327         ssize_t m_total;
328         union {
329                 struct aes_ccm_128_context ccm;
330                 struct aes_gcm_128_context gcm;
331         } c;
332         uint8_t key[AES_BLOCK_SIZE];
333
334         if (count < 1) {
335                 return NT_STATUS_INVALID_PARAMETER;
336         }
337
338         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
339                 return NT_STATUS_INVALID_PARAMETER;
340         }
341
342         tf = (uint8_t *)vector[0].iov_base;
343
344         if (encryption_key.length == 0) {
345                 DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
346                          (unsigned)encryption_key.length));
347                 return NT_STATUS_ACCESS_DENIED;
348         }
349
350         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
351
352         m_total = iov_buflen(&vector[1], count-1);
353         if (m_total == -1) {
354                 return NT_STATUS_BUFFER_TOO_SMALL;
355         }
356
357         SSVAL(tf, SMB2_TF_FLAGS, SMB2_TF_FLAGS_ENCRYPTED);
358         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
359
360         ZERO_STRUCT(key);
361         memcpy(key, encryption_key.data,
362                MIN(encryption_key.length, AES_BLOCK_SIZE));
363
364         switch (cipher_id) {
365         case SMB2_ENCRYPTION_AES128_CCM:
366                 aes_ccm_128_init(&c.ccm, key,
367                                  tf + SMB2_TF_NONCE,
368                                  a_total, m_total);
369                 memset(tf + SMB2_TF_NONCE + AES_CCM_128_NONCE_SIZE, 0,
370                        16 - AES_CCM_128_NONCE_SIZE);
371                 aes_ccm_128_update(&c.ccm, tf + SMB2_TF_NONCE, a_total);
372                 for (i=1; i < count; i++) {
373                         aes_ccm_128_update(&c.ccm,
374                                         (const uint8_t *)vector[i].iov_base,
375                                         vector[i].iov_len);
376                         aes_ccm_128_crypt(&c.ccm,
377                                         (uint8_t *)vector[i].iov_base,
378                                         vector[i].iov_len);
379                 }
380                 aes_ccm_128_digest(&c.ccm, sig);
381                 break;
382
383         case SMB2_ENCRYPTION_AES128_GCM:
384                 aes_gcm_128_init(&c.gcm, key, tf + SMB2_TF_NONCE);
385                 memset(tf + SMB2_TF_NONCE + AES_GCM_128_IV_SIZE, 0,
386                        16 - AES_GCM_128_IV_SIZE);
387                 aes_gcm_128_updateA(&c.gcm, tf + SMB2_TF_NONCE, a_total);
388                 for (i=1; i < count; i++) {
389                         aes_gcm_128_crypt(&c.gcm,
390                                         (uint8_t *)vector[i].iov_base,
391                                         vector[i].iov_len);
392                         aes_gcm_128_updateC(&c.gcm,
393                                         (const uint8_t *)vector[i].iov_base,
394                                         vector[i].iov_len);
395                 }
396                 aes_gcm_128_digest(&c.gcm, sig);
397                 break;
398
399         default:
400                 ZERO_STRUCT(key);
401                 return NT_STATUS_INVALID_PARAMETER;
402         }
403         ZERO_STRUCT(key);
404
405         memcpy(tf + SMB2_TF_SIGNATURE, sig, 16);
406
407         DEBUG(5,("encrypt SMB2 message\n"));
408
409         return NT_STATUS_OK;
410 }
411
412 NTSTATUS smb2_signing_decrypt_pdu(DATA_BLOB decryption_key,
413                                   uint16_t cipher_id,
414                                   struct iovec *vector,
415                                   int count)
416 {
417         uint8_t *tf;
418         uint16_t flags;
419         uint8_t *sig_ptr = NULL;
420         uint8_t sig[16];
421         int i;
422         size_t a_total;
423         ssize_t m_total;
424         uint32_t msg_size = 0;
425         union {
426                 struct aes_ccm_128_context ccm;
427                 struct aes_gcm_128_context gcm;
428         } c;
429         uint8_t key[AES_BLOCK_SIZE];
430
431         if (count < 1) {
432                 return NT_STATUS_INVALID_PARAMETER;
433         }
434
435         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
436                 return NT_STATUS_INVALID_PARAMETER;
437         }
438
439         tf = (uint8_t *)vector[0].iov_base;
440
441         if (decryption_key.length == 0) {
442                 DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
443                          (unsigned)decryption_key.length));
444                 return NT_STATUS_ACCESS_DENIED;
445         }
446
447         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
448
449         m_total = iov_buflen(&vector[1], count-1);
450         if (m_total == -1) {
451                 return NT_STATUS_BUFFER_TOO_SMALL;
452         }
453
454         flags = SVAL(tf, SMB2_TF_FLAGS);
455         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
456
457         if (flags != SMB2_TF_FLAGS_ENCRYPTED) {
458                 return NT_STATUS_ACCESS_DENIED;
459         }
460
461         if (msg_size != m_total) {
462                 return NT_STATUS_INTERNAL_ERROR;
463         }
464
465         ZERO_STRUCT(key);
466         memcpy(key, decryption_key.data,
467                MIN(decryption_key.length, AES_BLOCK_SIZE));
468
469         switch (cipher_id) {
470         case SMB2_ENCRYPTION_AES128_CCM:
471                 aes_ccm_128_init(&c.ccm, key,
472                                  tf + SMB2_TF_NONCE,
473                                  a_total, m_total);
474                 aes_ccm_128_update(&c.ccm, tf + SMB2_TF_NONCE, a_total);
475                 for (i=1; i < count; i++) {
476                         aes_ccm_128_crypt(&c.ccm,
477                                         (uint8_t *)vector[i].iov_base,
478                                         vector[i].iov_len);
479                         aes_ccm_128_update(&c.ccm,
480                                         ( uint8_t *)vector[i].iov_base,
481                                         vector[i].iov_len);
482                 }
483                 aes_ccm_128_digest(&c.ccm, sig);
484                 break;
485
486         case SMB2_ENCRYPTION_AES128_GCM:
487                 aes_gcm_128_init(&c.gcm, key, tf + SMB2_TF_NONCE);
488                 aes_gcm_128_updateA(&c.gcm, tf + SMB2_TF_NONCE, a_total);
489                 for (i=1; i < count; i++) {
490                         aes_gcm_128_updateC(&c.gcm,
491                                         (const uint8_t *)vector[i].iov_base,
492                                         vector[i].iov_len);
493                         aes_gcm_128_crypt(&c.gcm,
494                                         (uint8_t *)vector[i].iov_base,
495                                         vector[i].iov_len);
496                 }
497                 aes_gcm_128_digest(&c.gcm, sig);
498                 break;
499
500         default:
501                 ZERO_STRUCT(key);
502                 return NT_STATUS_INVALID_PARAMETER;
503         }
504         ZERO_STRUCT(key);
505
506         sig_ptr = tf + SMB2_TF_SIGNATURE;
507         if (memcmp(sig_ptr, sig, 16) != 0) {
508                 return NT_STATUS_ACCESS_DENIED;
509         }
510
511         DEBUG(5,("decrypt SMB2 message\n"));
512
513         return NT_STATUS_OK;
514 }