2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
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.
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.
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/>.
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"
27 NTSTATUS
smb2_signing_sign_pdu(DATA_BLOB signing_key
,
28 enum protocol_types protocol
,
38 return NT_STATUS_INVALID_PARAMETER
;
41 if (vector
[0].iov_len
!= SMB2_HDR_BODY
) {
42 return NT_STATUS_INVALID_PARAMETER
;
45 hdr
= (uint8_t *)vector
[0].iov_base
;
47 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
48 if (session_id
== 0) {
50 * do not sign messages with a zero session_id.
51 * See MS-SMB2 3.2.4.1.1
56 if (signing_key
.length
== 0) {
57 DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
58 (unsigned)signing_key
.length
));
59 return NT_STATUS_ACCESS_DENIED
;
62 memset(hdr
+ SMB2_HDR_SIGNATURE
, 0, 16);
64 SIVAL(hdr
, SMB2_HDR_FLAGS
, IVAL(hdr
, SMB2_HDR_FLAGS
) | SMB2_HDR_FLAG_SIGNED
);
66 if (protocol
>= PROTOCOL_SMB2_24
) {
67 struct aes_cmac_128_context ctx
;
68 uint8_t key
[AES_BLOCK_SIZE
];
71 memcpy(key
, signing_key
.data
, MIN(signing_key
.length
, 16));
73 aes_cmac_128_init(&ctx
, key
);
74 for (i
=0; i
< count
; i
++) {
75 aes_cmac_128_update(&ctx
,
76 (const uint8_t *)vector
[i
].iov_base
,
79 aes_cmac_128_final(&ctx
, res
);
81 struct HMACSHA256Context m
;
82 uint8_t digest
[SHA256_DIGEST_LENGTH
];
85 hmac_sha256_init(signing_key
.data
, MIN(signing_key
.length
, 16), &m
);
86 for (i
=0; i
< count
; i
++) {
87 hmac_sha256_update((const uint8_t *)vector
[i
].iov_base
,
88 vector
[i
].iov_len
, &m
);
90 hmac_sha256_final(digest
, &m
);
91 memcpy(res
, digest
, 16);
93 DEBUG(5,("signed SMB2 message\n"));
95 memcpy(hdr
+ SMB2_HDR_SIGNATURE
, res
, 16);
100 NTSTATUS
smb2_signing_check_pdu(DATA_BLOB signing_key
,
101 enum protocol_types protocol
,
102 const struct iovec
*vector
,
109 static const uint8_t zero_sig
[16] = { 0, };
113 return NT_STATUS_INVALID_PARAMETER
;
116 if (vector
[0].iov_len
!= SMB2_HDR_BODY
) {
117 return NT_STATUS_INVALID_PARAMETER
;
120 hdr
= (const uint8_t *)vector
[0].iov_base
;
122 session_id
= BVAL(hdr
, SMB2_HDR_SESSION_ID
);
123 if (session_id
== 0) {
125 * do not sign messages with a zero session_id.
126 * See MS-SMB2 3.2.4.1.1
131 if (signing_key
.length
== 0) {
132 /* we don't have the session key yet */
136 sig
= hdr
+SMB2_HDR_SIGNATURE
;
138 if (protocol
>= PROTOCOL_SMB2_24
) {
139 struct aes_cmac_128_context ctx
;
140 uint8_t key
[AES_BLOCK_SIZE
];
143 memcpy(key
, signing_key
.data
, MIN(signing_key
.length
, 16));
145 aes_cmac_128_init(&ctx
, key
);
146 aes_cmac_128_update(&ctx
, hdr
, SMB2_HDR_SIGNATURE
);
147 aes_cmac_128_update(&ctx
, zero_sig
, 16);
148 for (i
=1; i
< count
; i
++) {
149 aes_cmac_128_update(&ctx
,
150 (const uint8_t *)vector
[i
].iov_base
,
153 aes_cmac_128_final(&ctx
, res
);
155 struct HMACSHA256Context m
;
156 uint8_t digest
[SHA256_DIGEST_LENGTH
];
159 hmac_sha256_init(signing_key
.data
, MIN(signing_key
.length
, 16), &m
);
160 hmac_sha256_update(hdr
, SMB2_HDR_SIGNATURE
, &m
);
161 hmac_sha256_update(zero_sig
, 16, &m
);
162 for (i
=1; i
< count
; i
++) {
163 hmac_sha256_update((const uint8_t *)vector
[i
].iov_base
,
164 vector
[i
].iov_len
, &m
);
166 hmac_sha256_final(digest
, &m
);
167 memcpy(res
, digest
, 16);
170 if (memcmp(res
, sig
, 16) != 0) {
171 DEBUG(0,("Bad SMB2 signature for message\n"));
172 dump_data(0, sig
, 16);
173 dump_data(0, res
, 16);
174 return NT_STATUS_ACCESS_DENIED
;
180 void smb2_key_derivation(const uint8_t *KI
, size_t KI_len
,
181 const uint8_t *Label
, size_t Label_len
,
182 const uint8_t *Context
, size_t Context_len
,
185 struct HMACSHA256Context ctx
;
187 static const uint8_t zero
= 0;
188 uint8_t digest
[SHA256_DIGEST_LENGTH
];
193 * a simplified version of
194 * "NIST Special Publication 800-108" section 5.1
197 hmac_sha256_init(KI
, KI_len
, &ctx
);
200 hmac_sha256_update(buf
, sizeof(buf
), &ctx
);
201 hmac_sha256_update(Label
, Label_len
, &ctx
);
202 hmac_sha256_update(&zero
, 1, &ctx
);
203 hmac_sha256_update(Context
, Context_len
, &ctx
);
205 hmac_sha256_update(buf
, sizeof(buf
), &ctx
);
207 hmac_sha256_final(digest
, &ctx
);
209 memcpy(KO
, digest
, 16);
212 NTSTATUS
smb2_signing_encrypt_pdu(DATA_BLOB encryption_key
,
214 struct iovec
*vector
,
223 struct aes_ccm_128_context ccm
;
224 struct aes_gcm_128_context gcm
;
226 uint8_t key
[AES_BLOCK_SIZE
];
229 return NT_STATUS_INVALID_PARAMETER
;
232 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
233 return NT_STATUS_INVALID_PARAMETER
;
236 tf
= (uint8_t *)vector
[0].iov_base
;
238 if (encryption_key
.length
== 0) {
239 DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
240 (unsigned)encryption_key
.length
));
241 return NT_STATUS_ACCESS_DENIED
;
244 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
246 m_total
= iov_buflen(&vector
[1], count
-1);
248 return NT_STATUS_BUFFER_TOO_SMALL
;
251 SSVAL(tf
, SMB2_TF_FLAGS
, SMB2_TF_FLAGS_ENCRYPTED
);
252 SIVAL(tf
, SMB2_TF_MSG_SIZE
, m_total
);
255 memcpy(key
, encryption_key
.data
,
256 MIN(encryption_key
.length
, AES_BLOCK_SIZE
));
259 case SMB2_ENCRYPTION_AES128_CCM
:
260 aes_ccm_128_init(&c
.ccm
, key
,
263 memset(tf
+ SMB2_TF_NONCE
+ AES_CCM_128_NONCE_SIZE
, 0,
264 16 - AES_CCM_128_NONCE_SIZE
);
265 aes_ccm_128_update(&c
.ccm
, tf
+ SMB2_TF_NONCE
, a_total
);
266 for (i
=1; i
< count
; i
++) {
267 aes_ccm_128_update(&c
.ccm
,
268 (const uint8_t *)vector
[i
].iov_base
,
270 aes_ccm_128_crypt(&c
.ccm
,
271 (uint8_t *)vector
[i
].iov_base
,
274 aes_ccm_128_digest(&c
.ccm
, sig
);
277 case SMB2_ENCRYPTION_AES128_GCM
:
278 aes_gcm_128_init(&c
.gcm
, key
, tf
+ SMB2_TF_NONCE
);
279 memset(tf
+ SMB2_TF_NONCE
+ AES_GCM_128_IV_SIZE
, 0,
280 16 - AES_GCM_128_IV_SIZE
);
281 aes_gcm_128_updateA(&c
.gcm
, tf
+ SMB2_TF_NONCE
, a_total
);
282 for (i
=1; i
< count
; i
++) {
283 aes_gcm_128_crypt(&c
.gcm
,
284 (uint8_t *)vector
[i
].iov_base
,
286 aes_gcm_128_updateC(&c
.gcm
,
287 (const uint8_t *)vector
[i
].iov_base
,
290 aes_gcm_128_digest(&c
.gcm
, sig
);
295 return NT_STATUS_INVALID_PARAMETER
;
299 memcpy(tf
+ SMB2_TF_SIGNATURE
, sig
, 16);
301 DEBUG(5,("encrypt SMB2 message\n"));
306 NTSTATUS
smb2_signing_decrypt_pdu(DATA_BLOB decryption_key
,
308 struct iovec
*vector
,
313 uint8_t *sig_ptr
= NULL
;
318 uint32_t msg_size
= 0;
320 struct aes_ccm_128_context ccm
;
321 struct aes_gcm_128_context gcm
;
323 uint8_t key
[AES_BLOCK_SIZE
];
326 return NT_STATUS_INVALID_PARAMETER
;
329 if (vector
[0].iov_len
!= SMB2_TF_HDR_SIZE
) {
330 return NT_STATUS_INVALID_PARAMETER
;
333 tf
= (uint8_t *)vector
[0].iov_base
;
335 if (decryption_key
.length
== 0) {
336 DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
337 (unsigned)decryption_key
.length
));
338 return NT_STATUS_ACCESS_DENIED
;
341 a_total
= SMB2_TF_HDR_SIZE
- SMB2_TF_NONCE
;
343 m_total
= iov_buflen(&vector
[1], count
-1);
345 return NT_STATUS_BUFFER_TOO_SMALL
;
348 flags
= SVAL(tf
, SMB2_TF_FLAGS
);
349 msg_size
= IVAL(tf
, SMB2_TF_MSG_SIZE
);
351 if (flags
!= SMB2_TF_FLAGS_ENCRYPTED
) {
352 return NT_STATUS_ACCESS_DENIED
;
355 if (msg_size
!= m_total
) {
356 return NT_STATUS_INTERNAL_ERROR
;
360 memcpy(key
, decryption_key
.data
,
361 MIN(decryption_key
.length
, AES_BLOCK_SIZE
));
364 case SMB2_ENCRYPTION_AES128_CCM
:
365 aes_ccm_128_init(&c
.ccm
, key
,
368 aes_ccm_128_update(&c
.ccm
, tf
+ SMB2_TF_NONCE
, a_total
);
369 for (i
=1; i
< count
; i
++) {
370 aes_ccm_128_crypt(&c
.ccm
,
371 (uint8_t *)vector
[i
].iov_base
,
373 aes_ccm_128_update(&c
.ccm
,
374 ( uint8_t *)vector
[i
].iov_base
,
377 aes_ccm_128_digest(&c
.ccm
, sig
);
380 case SMB2_ENCRYPTION_AES128_GCM
:
381 aes_gcm_128_init(&c
.gcm
, key
, tf
+ SMB2_TF_NONCE
);
382 aes_gcm_128_updateA(&c
.gcm
, tf
+ SMB2_TF_NONCE
, a_total
);
383 for (i
=1; i
< count
; i
++) {
384 aes_gcm_128_updateC(&c
.gcm
,
385 (const uint8_t *)vector
[i
].iov_base
,
387 aes_gcm_128_crypt(&c
.gcm
,
388 (uint8_t *)vector
[i
].iov_base
,
391 aes_gcm_128_digest(&c
.gcm
, sig
);
396 return NT_STATUS_INVALID_PARAMETER
;
400 sig_ptr
= tf
+ SMB2_TF_SIGNATURE
;
401 if (memcmp(sig_ptr
, sig
, 16) != 0) {
402 return NT_STATUS_ACCESS_DENIED
;
405 DEBUG(5,("decrypt SMB2 message\n"));