2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "lib/crypto/crypto.h"
26 struct schannel_state
{
27 uint8_t session_key
[16];
32 #define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
33 #define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
35 /*******************************************************************
36 Encode or Decode the sequence number (which is symmetric)
37 ********************************************************************/
38 static void netsec_deal_with_seq_num(struct schannel_state
*state
,
39 const uint8_t packet_digest
[8],
42 static const uint8_t zeros
[4];
43 uint8_t sequence_key
[16];
46 hmac_md5(state
->session_key
, zeros
, sizeof(zeros
), digest1
);
47 hmac_md5(digest1
, packet_digest
, 8, sequence_key
);
48 arcfour_crypt(seq_num
, sequence_key
, 8);
54 /*******************************************************************
55 Calculate the key with which to encode the data payload
56 ********************************************************************/
57 static void netsec_get_sealing_key(const uint8_t session_key
[16],
58 const uint8_t seq_num
[8],
59 uint8_t sealing_key
[16])
61 static const uint8_t zeros
[4];
66 for (i
= 0; i
< 16; i
++) {
67 sess_kf0
[i
] = session_key
[i
] ^ 0xf0;
70 hmac_md5(sess_kf0
, zeros
, 4, digest2
);
71 hmac_md5(digest2
, seq_num
, 8, sealing_key
);
75 /*******************************************************************
76 Create a digest over the entire packet (including the data), and
77 MD5 it with the session key.
78 ********************************************************************/
79 static void schannel_digest(const uint8_t sess_key
[16],
80 const uint8_t netsec_sig
[8],
81 const uint8_t *confounder
,
82 const uint8_t *data
, size_t data_len
,
83 uint8_t digest_final
[16])
85 uint8_t packet_digest
[16];
86 static const uint8_t zeros
[4];
87 struct MD5Context ctx
;
90 MD5Update(&ctx
, zeros
, 4);
91 MD5Update(&ctx
, netsec_sig
, 8);
93 MD5Update(&ctx
, confounder
, 8);
95 MD5Update(&ctx
, data
, data_len
);
96 MD5Final(packet_digest
, &ctx
);
98 hmac_md5(sess_key
, packet_digest
, sizeof(packet_digest
), digest_final
);
105 NTSTATUS
schannel_unseal_packet(struct schannel_state
*state
,
107 uint8_t *data
, size_t length
,
110 uint8_t digest_final
[16];
111 uint8_t confounder
[8];
113 uint8_t sealing_key
[16];
114 static const uint8_t netsec_sig
[8] = NETSEC_SEAL_SIGNATURE
;
116 if (sig
->length
!= 32) {
117 return NT_STATUS_ACCESS_DENIED
;
120 memcpy(confounder
, sig
->data
+24, 8);
122 RSIVAL(seq_num
, 0, state
->seq_num
);
123 SIVAL(seq_num
, 4, state
->initiator
?0:0x80);
125 netsec_get_sealing_key(state
->session_key
, seq_num
, sealing_key
);
126 arcfour_crypt(confounder
, sealing_key
, 8);
127 arcfour_crypt(data
, sealing_key
, length
);
129 schannel_digest(state
->session_key
,
130 netsec_sig
, confounder
,
131 data
, length
, digest_final
);
133 if (memcmp(digest_final
, sig
->data
+16, 8) != 0) {
134 dump_data_pw("calc digest:", digest_final
, 8);
135 dump_data_pw("wire digest:", sig
->data
+16, 8);
136 return NT_STATUS_ACCESS_DENIED
;
139 netsec_deal_with_seq_num(state
, digest_final
, seq_num
);
141 if (memcmp(seq_num
, sig
->data
+8, 8) != 0) {
142 dump_data_pw("calc seq num:", seq_num
, 8);
143 dump_data_pw("wire seq num:", sig
->data
+8, 8);
144 return NT_STATUS_ACCESS_DENIED
;
151 check the signature on a packet
153 NTSTATUS
schannel_check_packet(struct schannel_state
*state
,
154 const uint8_t *data
, size_t length
,
155 const DATA_BLOB
*sig
)
157 uint8_t digest_final
[16];
159 static const uint8_t netsec_sig
[8] = NETSEC_SIGN_SIGNATURE
;
161 /* w2k sends just 24 bytes and skip the confounder */
162 if (sig
->length
!= 32 && sig
->length
!= 24) {
163 return NT_STATUS_ACCESS_DENIED
;
166 RSIVAL(seq_num
, 0, state
->seq_num
);
167 SIVAL(seq_num
, 4, state
->initiator
?0:0x80);
169 dump_data_pw("seq_num:\n", seq_num
, 8);
170 dump_data_pw("sess_key:\n", state
->session_key
, 16);
172 schannel_digest(state
->session_key
,
174 data
, length
, digest_final
);
176 netsec_deal_with_seq_num(state
, digest_final
, seq_num
);
178 if (memcmp(seq_num
, sig
->data
+8, 8) != 0) {
179 dump_data_pw("calc seq num:", seq_num
, 8);
180 dump_data_pw("wire seq num:", sig
->data
+8, 8);
181 return NT_STATUS_ACCESS_DENIED
;
184 if (memcmp(digest_final
, sig
->data
+16, 8) != 0) {
185 dump_data_pw("calc digest:", digest_final
, 8);
186 dump_data_pw("wire digest:", sig
->data
+16, 8);
187 return NT_STATUS_ACCESS_DENIED
;
197 NTSTATUS
schannel_seal_packet(struct schannel_state
*state
,
199 uint8_t *data
, size_t length
,
202 uint8_t digest_final
[16];
203 uint8_t confounder
[8];
205 uint8_t sealing_key
[16];
206 static const uint8_t netsec_sig
[8] = NETSEC_SEAL_SIGNATURE
;
208 generate_random_buffer(confounder
, 8);
210 RSIVAL(seq_num
, 0, state
->seq_num
);
211 SIVAL(seq_num
, 4, state
->initiator
?0x80:0);
213 schannel_digest(state
->session_key
,
214 netsec_sig
, confounder
,
215 data
, length
, digest_final
);
217 netsec_get_sealing_key(state
->session_key
, seq_num
, sealing_key
);
218 arcfour_crypt(confounder
, sealing_key
, 8);
219 arcfour_crypt(data
, sealing_key
, length
);
221 netsec_deal_with_seq_num(state
, digest_final
, seq_num
);
223 (*sig
) = data_blob_talloc(mem_ctx
, NULL
, 32);
225 memcpy(sig
->data
, netsec_sig
, 8);
226 memcpy(sig
->data
+8, seq_num
, 8);
227 memcpy(sig
->data
+16, digest_final
, 8);
228 memcpy(sig
->data
+24, confounder
, 8);
230 dump_data_pw("signature:", sig
->data
+ 0, 8);
231 dump_data_pw("seq_num :", sig
->data
+ 8, 8);
232 dump_data_pw("digest :", sig
->data
+16, 8);
233 dump_data_pw("confound :", sig
->data
+24, 8);
242 NTSTATUS
schannel_sign_packet(struct schannel_state
*state
,
244 const uint8_t *data
, size_t length
,
247 uint8_t digest_final
[16];
249 static const uint8_t netsec_sig
[8] = NETSEC_SIGN_SIGNATURE
;
251 RSIVAL(seq_num
, 0, state
->seq_num
);
252 SIVAL(seq_num
, 4, state
->initiator
?0x80:0);
254 schannel_digest(state
->session_key
,
256 data
, length
, digest_final
);
258 netsec_deal_with_seq_num(state
, digest_final
, seq_num
);
260 (*sig
) = data_blob_talloc(mem_ctx
, NULL
, 32);
262 memcpy(sig
->data
, netsec_sig
, 8);
263 memcpy(sig
->data
+8, seq_num
, 8);
264 memcpy(sig
->data
+16, digest_final
, 8);
265 memset(sig
->data
+24, 0, 8);
267 dump_data_pw("signature:", sig
->data
+ 0, 8);
268 dump_data_pw("seq_num :", sig
->data
+ 8, 8);
269 dump_data_pw("digest :", sig
->data
+16, 8);
270 dump_data_pw("confound :", sig
->data
+24, 8);
276 create an schannel context state
278 NTSTATUS
schannel_start(TALLOC_CTX
*mem_ctx
,
279 struct schannel_state
**state
,
280 const uint8_t session_key
[16],
283 (*state
) = talloc(mem_ctx
, struct schannel_state
);
285 return NT_STATUS_NO_MEMORY
;
288 memcpy((*state
)->session_key
, session_key
, 16);
289 (*state
)->initiator
= initiator
;
290 (*state
)->seq_num
= 0;