2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "../libcli/auth/schannel.h"
25 #include "../lib/crypto/crypto.h"
27 static void netsec_offset_and_sizes(struct schannel_state
*state
,
29 uint32_t *_min_sig_size
,
30 uint32_t *_used_sig_size
,
31 uint32_t *_checksum_length
,
32 uint32_t *_confounder_ofs
)
34 uint32_t min_sig_size
;
35 uint32_t used_sig_size
;
36 uint32_t checksum_length
;
37 uint32_t confounder_ofs
;
39 if (state
->creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
43 * Note: windows has a bug here and uses the old values...
45 * checksum_length = 32;
46 * confounder_ofs = 48;
62 *_min_sig_size
= min_sig_size
;
66 *_used_sig_size
= used_sig_size
;
69 if (_checksum_length
) {
70 *_checksum_length
= checksum_length
;
73 if (_confounder_ofs
) {
74 *_confounder_ofs
= confounder_ofs
;
78 /*******************************************************************
79 Encode or Decode the sequence number (which is symmetric)
80 ********************************************************************/
81 static void netsec_do_seq_num(struct schannel_state
*state
,
82 const uint8_t *checksum
,
83 uint32_t checksum_length
,
86 if (state
->creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
88 uint8_t iv
[AES_BLOCK_SIZE
];
90 AES_set_encrypt_key(state
->creds
->session_key
, 128, &key
);
92 memcpy(iv
+0, checksum
, 8);
93 memcpy(iv
+8, checksum
, 8);
95 aes_cfb8_encrypt(seq_num
, seq_num
, 8, &key
, iv
, AES_ENCRYPT
);
97 static const uint8_t zeros
[4];
98 uint8_t sequence_key
[16];
101 hmac_md5(state
->creds
->session_key
, zeros
, sizeof(zeros
), digest1
);
102 hmac_md5(digest1
, checksum
, checksum_length
, sequence_key
);
103 arcfour_crypt(seq_num
, sequence_key
, 8);
109 static void netsec_do_seal(struct schannel_state
*state
,
110 const uint8_t seq_num
[8],
111 uint8_t confounder
[8],
112 uint8_t *data
, uint32_t length
,
115 if (state
->creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
117 uint8_t iv
[AES_BLOCK_SIZE
];
118 uint8_t sess_kf0
[16];
121 for (i
= 0; i
< 16; i
++) {
122 sess_kf0
[i
] = state
->creds
->session_key
[i
] ^ 0xf0;
125 AES_set_encrypt_key(sess_kf0
, 128, &key
);
127 memcpy(iv
+0, seq_num
, 8);
128 memcpy(iv
+8, seq_num
, 8);
131 aes_cfb8_encrypt(confounder
, confounder
, 8, &key
, iv
, AES_ENCRYPT
);
132 aes_cfb8_encrypt(data
, data
, length
, &key
, iv
, AES_ENCRYPT
);
134 aes_cfb8_encrypt(confounder
, confounder
, 8, &key
, iv
, AES_DECRYPT
);
135 aes_cfb8_encrypt(data
, data
, length
, &key
, iv
, AES_DECRYPT
);
138 uint8_t sealing_key
[16];
139 static const uint8_t zeros
[4];
141 uint8_t sess_kf0
[16];
144 for (i
= 0; i
< 16; i
++) {
145 sess_kf0
[i
] = state
->creds
->session_key
[i
] ^ 0xf0;
148 hmac_md5(sess_kf0
, zeros
, 4, digest2
);
149 hmac_md5(digest2
, seq_num
, 8, sealing_key
);
151 arcfour_crypt(confounder
, sealing_key
, 8);
152 arcfour_crypt(data
, sealing_key
, length
);
156 /*******************************************************************
157 Create a digest over the entire packet (including the data), and
158 MD5 it with the session key.
159 ********************************************************************/
160 static void netsec_do_sign(struct schannel_state
*state
,
161 const uint8_t *confounder
,
162 const uint8_t *data
, size_t length
,
166 if (state
->creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
167 struct HMACSHA256Context ctx
;
169 hmac_sha256_init(state
->creds
->session_key
,
170 sizeof(state
->creds
->session_key
),
174 SSVAL(header
, 0, NL_SIGN_HMAC_SHA256
);
175 SSVAL(header
, 2, NL_SEAL_AES128
);
176 SSVAL(header
, 4, 0xFFFF);
177 SSVAL(header
, 6, 0x0000);
179 hmac_sha256_update(header
, 8, &ctx
);
180 hmac_sha256_update(confounder
, 8, &ctx
);
182 SSVAL(header
, 0, NL_SIGN_HMAC_SHA256
);
183 SSVAL(header
, 2, NL_SEAL_NONE
);
184 SSVAL(header
, 4, 0xFFFF);
185 SSVAL(header
, 6, 0x0000);
187 hmac_sha256_update(header
, 8, &ctx
);
190 hmac_sha256_update(data
, length
, &ctx
);
192 hmac_sha256_final(checksum
, &ctx
);
194 uint8_t packet_digest
[16];
195 static const uint8_t zeros
[4];
196 struct MD5Context ctx
;
199 MD5Update(&ctx
, zeros
, 4);
201 SSVAL(header
, 0, NL_SIGN_HMAC_MD5
);
202 SSVAL(header
, 2, NL_SEAL_RC4
);
203 SSVAL(header
, 4, 0xFFFF);
204 SSVAL(header
, 6, 0x0000);
206 MD5Update(&ctx
, header
, 8);
207 MD5Update(&ctx
, confounder
, 8);
209 SSVAL(header
, 0, NL_SIGN_HMAC_MD5
);
210 SSVAL(header
, 2, NL_SEAL_NONE
);
211 SSVAL(header
, 4, 0xFFFF);
212 SSVAL(header
, 6, 0x0000);
214 MD5Update(&ctx
, header
, 8);
216 MD5Update(&ctx
, data
, length
);
217 MD5Final(packet_digest
, &ctx
);
219 hmac_md5(state
->creds
->session_key
,
220 packet_digest
, sizeof(packet_digest
),
225 NTSTATUS
netsec_incoming_packet(struct schannel_state
*state
,
227 uint8_t *data
, size_t length
,
228 const DATA_BLOB
*sig
)
230 uint32_t min_sig_size
= 0;
232 uint8_t checksum
[32];
233 uint32_t checksum_length
= sizeof(checksum_length
);
234 uint8_t _confounder
[8];
235 uint8_t *confounder
= NULL
;
236 uint32_t confounder_ofs
= 0;
240 netsec_offset_and_sizes(state
,
247 if (sig
->length
< min_sig_size
) {
248 return NT_STATUS_ACCESS_DENIED
;
252 confounder
= _confounder
;
253 memcpy(confounder
, sig
->data
+confounder_ofs
, 8);
258 RSIVAL(seq_num
, 0, state
->seq_num
);
259 SIVAL(seq_num
, 4, state
->initiator
?0:0x80);
262 netsec_do_seal(state
, seq_num
,
268 netsec_do_sign(state
, confounder
,
272 ret
= memcmp(checksum
, sig
->data
+16, checksum_length
);
274 dump_data_pw("calc digest:", checksum
, checksum_length
);
275 dump_data_pw("wire digest:", sig
->data
+16, checksum_length
);
276 return NT_STATUS_ACCESS_DENIED
;
279 netsec_do_seq_num(state
, checksum
, checksum_length
, seq_num
);
281 ret
= memcmp(seq_num
, sig
->data
+8, 8);
283 dump_data_pw("calc seq num:", seq_num
, 8);
284 dump_data_pw("wire seq num:", sig
->data
+8, 8);
285 return NT_STATUS_ACCESS_DENIED
;
291 uint32_t netsec_outgoing_sig_size(struct schannel_state
*state
)
293 uint32_t sig_size
= 0;
295 netsec_offset_and_sizes(state
,
305 NTSTATUS
netsec_outgoing_packet(struct schannel_state
*state
,
308 uint8_t *data
, size_t length
,
311 uint32_t min_sig_size
= 0;
312 uint32_t used_sig_size
= 0;
314 uint8_t checksum
[32];
315 uint32_t checksum_length
= sizeof(checksum_length
);
316 uint8_t _confounder
[8];
317 uint8_t *confounder
= NULL
;
318 uint32_t confounder_ofs
= 0;
321 netsec_offset_and_sizes(state
,
328 RSIVAL(seq_num
, 0, state
->seq_num
);
329 SIVAL(seq_num
, 4, state
->initiator
?0x80:0);
332 confounder
= _confounder
;
333 generate_random_buffer(confounder
, 8);
338 netsec_do_sign(state
, confounder
,
343 netsec_do_seal(state
, seq_num
,
349 netsec_do_seq_num(state
, checksum
, checksum_length
, seq_num
);
351 (*sig
) = data_blob_talloc_zero(mem_ctx
, used_sig_size
);
353 memcpy(sig
->data
, header
, 8);
354 memcpy(sig
->data
+8, seq_num
, 8);
355 memcpy(sig
->data
+16, checksum
, checksum_length
);
358 memcpy(sig
->data
+confounder_ofs
, confounder
, 8);
361 dump_data_pw("signature:", sig
->data
+ 0, 8);
362 dump_data_pw("seq_num :", sig
->data
+ 8, 8);
363 dump_data_pw("digest :", sig
->data
+16, checksum_length
);
364 dump_data_pw("confound :", sig
->data
+confounder_ofs
, 8);