s3:smbd: remove code duplication in smb2_create_send()
[obnox/samba/samba-obnox.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
26 NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
27                                enum protocol_types protocol,
28                                struct iovec *vector,
29                                int count)
30 {
31         uint8_t *hdr;
32         uint64_t session_id;
33         uint8_t res[16];
34         int i;
35
36         if (count < 2) {
37                 return NT_STATUS_INVALID_PARAMETER;
38         }
39
40         if (vector[0].iov_len != SMB2_HDR_BODY) {
41                 return NT_STATUS_INVALID_PARAMETER;
42         }
43
44         hdr = (uint8_t *)vector[0].iov_base;
45
46         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
47         if (session_id == 0) {
48                 /*
49                  * do not sign messages with a zero session_id.
50                  * See MS-SMB2 3.2.4.1.1
51                  */
52                 return NT_STATUS_OK;
53         }
54
55         if (signing_key.length == 0) {
56                 DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
57                          (unsigned)signing_key.length));
58                 return NT_STATUS_ACCESS_DENIED;
59         }
60
61         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
62
63         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
64
65         if (protocol >= PROTOCOL_SMB2_24) {
66                 struct aes_cmac_128_context ctx;
67                 uint8_t key[AES_BLOCK_SIZE];
68
69                 ZERO_STRUCT(key);
70                 memcpy(key, signing_key.data, MIN(signing_key.length, 16));
71
72                 aes_cmac_128_init(&ctx, key);
73                 for (i=0; i < count; i++) {
74                         aes_cmac_128_update(&ctx,
75                                         (const uint8_t *)vector[i].iov_base,
76                                         vector[i].iov_len);
77                 }
78                 aes_cmac_128_final(&ctx, res);
79         } else {
80                 struct HMACSHA256Context m;
81                 uint8_t digest[SHA256_DIGEST_LENGTH];
82
83                 ZERO_STRUCT(m);
84                 hmac_sha256_init(signing_key.data, MIN(signing_key.length, 16), &m);
85                 for (i=0; i < count; i++) {
86                         hmac_sha256_update((const uint8_t *)vector[i].iov_base,
87                                            vector[i].iov_len, &m);
88                 }
89                 hmac_sha256_final(digest, &m);
90                 memcpy(res, digest, 16);
91         }
92         DEBUG(5,("signed SMB2 message\n"));
93
94         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
95
96         return NT_STATUS_OK;
97 }
98
99 NTSTATUS smb2_signing_check_pdu(DATA_BLOB signing_key,
100                                 enum protocol_types protocol,
101                                 const struct iovec *vector,
102                                 int count)
103 {
104         const uint8_t *hdr;
105         const uint8_t *sig;
106         uint64_t session_id;
107         uint8_t res[16];
108         static const uint8_t zero_sig[16] = { 0, };
109         int i;
110
111         if (count < 2) {
112                 return NT_STATUS_INVALID_PARAMETER;
113         }
114
115         if (vector[0].iov_len != SMB2_HDR_BODY) {
116                 return NT_STATUS_INVALID_PARAMETER;
117         }
118
119         hdr = (const uint8_t *)vector[0].iov_base;
120
121         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
122         if (session_id == 0) {
123                 /*
124                  * do not sign messages with a zero session_id.
125                  * See MS-SMB2 3.2.4.1.1
126                  */
127                 return NT_STATUS_OK;
128         }
129
130         if (signing_key.length == 0) {
131                 /* we don't have the session key yet */
132                 return NT_STATUS_OK;
133         }
134
135         sig = hdr+SMB2_HDR_SIGNATURE;
136
137         if (protocol >= PROTOCOL_SMB2_24) {
138                 struct aes_cmac_128_context ctx;
139                 uint8_t key[AES_BLOCK_SIZE];
140
141                 ZERO_STRUCT(key);
142                 memcpy(key, signing_key.data, MIN(signing_key.length, 16));
143
144                 aes_cmac_128_init(&ctx, key);
145                 aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
146                 aes_cmac_128_update(&ctx, zero_sig, 16);
147                 for (i=1; i < count; i++) {
148                         aes_cmac_128_update(&ctx,
149                                         (const uint8_t *)vector[i].iov_base,
150                                         vector[i].iov_len);
151                 }
152                 aes_cmac_128_final(&ctx, res);
153         } else {
154                 struct HMACSHA256Context m;
155                 uint8_t digest[SHA256_DIGEST_LENGTH];
156
157                 ZERO_STRUCT(m);
158                 hmac_sha256_init(signing_key.data, MIN(signing_key.length, 16), &m);
159                 hmac_sha256_update(hdr, SMB2_HDR_SIGNATURE, &m);
160                 hmac_sha256_update(zero_sig, 16, &m);
161                 for (i=1; i < count; i++) {
162                         hmac_sha256_update((const uint8_t *)vector[i].iov_base,
163                                            vector[i].iov_len, &m);
164                 }
165                 hmac_sha256_final(digest, &m);
166                 memcpy(res, digest, 16);
167         }
168
169         if (memcmp(res, sig, 16) != 0) {
170                 DEBUG(0,("Bad SMB2 signature for message\n"));
171                 dump_data(0, sig, 16);
172                 dump_data(0, res, 16);
173                 return NT_STATUS_ACCESS_DENIED;
174         }
175
176         return NT_STATUS_OK;
177 }
178
179 void smb2_key_derivation(const uint8_t *KI, size_t KI_len,
180                          const uint8_t *Label, size_t Label_len,
181                          const uint8_t *Context, size_t Context_len,
182                          uint8_t KO[16])
183 {
184         struct HMACSHA256Context ctx;
185         uint8_t buf[4];
186         static const uint8_t zero = 0;
187         uint8_t digest[SHA256_DIGEST_LENGTH];
188         uint32_t i = 1;
189         uint32_t L = 128;
190
191         /*
192          * a simplified version of
193          * "NIST Special Publication 800-108" section 5.1
194          * using hmac-sha256.
195          */
196         hmac_sha256_init(KI, KI_len, &ctx);
197
198         RSIVAL(buf, 0, i);
199         hmac_sha256_update(buf, sizeof(buf), &ctx);
200         hmac_sha256_update(Label, Label_len, &ctx);
201         hmac_sha256_update(&zero, 1, &ctx);
202         hmac_sha256_update(Context, Context_len, &ctx);
203         RSIVAL(buf, 0, L);
204         hmac_sha256_update(buf, sizeof(buf), &ctx);
205
206         hmac_sha256_final(digest, &ctx);
207
208         memcpy(KO, digest, 16);
209 }
210
211 NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key,
212                                   enum protocol_types protocol,
213                                   struct iovec *vector,
214                                   int count)
215 {
216         uint8_t *tf;
217         uint16_t alg;
218         uint8_t sig[16];
219         int i;
220         size_t a_total;
221         size_t m_total = 0;
222         struct aes_ccm_128_context ctx;
223         uint8_t key[AES_BLOCK_SIZE];
224
225         if (count < 1) {
226                 return NT_STATUS_INVALID_PARAMETER;
227         }
228
229         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
230                 return NT_STATUS_INVALID_PARAMETER;
231         }
232
233         tf = (uint8_t *)vector[0].iov_base;
234
235         if (encryption_key.length == 0) {
236                 DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
237                          (unsigned)encryption_key.length));
238                 return NT_STATUS_ACCESS_DENIED;
239         }
240
241         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
242         for (i=1; i < count; i++) {
243                 m_total += vector[i].iov_len;
244         }
245
246         alg = SMB2_ENCRYPTION_AES128_CCM;
247         SSVAL(tf, SMB2_TF_ALGORITHM, alg);
248         SIVAL(tf, SMB2_TF_MSG_SIZE, m_total);
249
250         ZERO_STRUCT(key);
251         memcpy(key, encryption_key.data,
252                MIN(encryption_key.length, AES_BLOCK_SIZE));
253         aes_ccm_128_init(&ctx, key,
254                          tf + SMB2_TF_NONCE,
255                          a_total, m_total);
256         aes_ccm_128_update(&ctx, tf + SMB2_TF_NONCE, a_total);
257         for (i=1; i < count; i++) {
258                 aes_ccm_128_update(&ctx,
259                                 (const uint8_t *)vector[i].iov_base,
260                                 vector[i].iov_len);
261         }
262         for (i=1; i < count; i++) {
263                 aes_ccm_128_crypt(&ctx,
264                                 (uint8_t *)vector[i].iov_base,
265                                 vector[i].iov_len);
266         }
267         aes_ccm_128_digest(&ctx, sig);
268
269         memcpy(tf + SMB2_TF_SIGNATURE, sig, 16);
270
271         DEBUG(5,("encrypt SMB2 message\n"));
272
273         return NT_STATUS_OK;
274 }
275
276 NTSTATUS smb2_signing_decrypt_pdu(DATA_BLOB decryption_key,
277                                   enum protocol_types protocol,
278                                   struct iovec *vector,
279                                   int count)
280 {
281         uint8_t *tf;
282         uint16_t alg;
283         uint8_t *sig_ptr = NULL;
284         uint8_t sig[16];
285         int i;
286         size_t a_total;
287         size_t m_total = 0;
288         uint32_t msg_size = 0;
289         struct aes_ccm_128_context ctx;
290         uint8_t key[AES_BLOCK_SIZE];
291
292         if (count < 1) {
293                 return NT_STATUS_INVALID_PARAMETER;
294         }
295
296         if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
297                 return NT_STATUS_INVALID_PARAMETER;
298         }
299
300         tf = (uint8_t *)vector[0].iov_base;
301
302         if (decryption_key.length == 0) {
303                 DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
304                          (unsigned)decryption_key.length));
305                 return NT_STATUS_ACCESS_DENIED;
306         }
307
308         a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
309         for (i=1; i < count; i++) {
310                 m_total += vector[i].iov_len;
311         }
312
313         alg = SVAL(tf, SMB2_TF_ALGORITHM);
314         msg_size = IVAL(tf, SMB2_TF_MSG_SIZE);
315
316         if (alg != SMB2_ENCRYPTION_AES128_CCM) {
317                 return NT_STATUS_ACCESS_DENIED;
318         }
319
320         if (msg_size != m_total) {
321                 return NT_STATUS_INTERNAL_ERROR;
322         }
323
324         ZERO_STRUCT(key);
325         memcpy(key, decryption_key.data,
326                MIN(decryption_key.length, AES_BLOCK_SIZE));
327         aes_ccm_128_init(&ctx, key,
328                          tf + SMB2_TF_NONCE,
329                          a_total, m_total);
330         for (i=1; i < count; i++) {
331                 aes_ccm_128_crypt(&ctx,
332                                 (uint8_t *)vector[i].iov_base,
333                                 vector[i].iov_len);
334         }
335         aes_ccm_128_update(&ctx, tf + SMB2_TF_NONCE, a_total);
336         for (i=1; i < count; i++) {
337                 aes_ccm_128_update(&ctx,
338                                 ( uint8_t *)vector[i].iov_base,
339                                 vector[i].iov_len);
340         }
341         aes_ccm_128_digest(&ctx, sig);
342
343         sig_ptr = tf + SMB2_TF_SIGNATURE;
344         if (memcmp(sig_ptr, sig, 16) != 0) {
345                 return NT_STATUS_ACCESS_DENIED;
346         }
347
348         DEBUG(5,("decrypt SMB2 message\n"));
349
350         return NT_STATUS_OK;
351 }