/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- netsec_deal_with_seq_num
- netsec_get_sealing_key
- schannel_digest
- schannel_unseal_packet
- schannel_check_packet
- schannel_seal_packet
- schannel_sign_packet
1 /*
2 Unix SMB/CIFS implementation.
3
4 schannel library code
5
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
8
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.
13
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.
18
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/>.
21 */
22
23 #include "includes.h"
24 #include "../lib/crypto/crypto.h"
25 #include "auth/auth.h"
26 #include "auth/gensec/schannel.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth/gensec/schannel_proto.h"
30
31 #define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
32 #define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
33
34 /*******************************************************************
35 Encode or Decode the sequence number (which is symmetric)
36 ********************************************************************/
37 static void netsec_deal_with_seq_num(struct schannel_state *state,
/* [<][>][^][v][top][bottom][index][help] */
38 const uint8_t packet_digest[8],
39 uint8_t seq_num[8])
40 {
41 static const uint8_t zeros[4];
42 uint8_t sequence_key[16];
43 uint8_t digest1[16];
44
45 hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1);
46 hmac_md5(digest1, packet_digest, 8, sequence_key);
47 arcfour_crypt(seq_num, sequence_key, 8);
48
49 state->seq_num++;
50 }
51
52
53 /*******************************************************************
54 Calculate the key with which to encode the data payload
55 ********************************************************************/
56 static void netsec_get_sealing_key(const uint8_t session_key[16],
/* [<][>][^][v][top][bottom][index][help] */
57 const uint8_t seq_num[8],
58 uint8_t sealing_key[16])
59 {
60 static const uint8_t zeros[4];
61 uint8_t digest2[16];
62 uint8_t sess_kf0[16];
63 int i;
64
65 for (i = 0; i < 16; i++) {
66 sess_kf0[i] = session_key[i] ^ 0xf0;
67 }
68
69 hmac_md5(sess_kf0, zeros, 4, digest2);
70 hmac_md5(digest2, seq_num, 8, sealing_key);
71 }
72
73
74 /*******************************************************************
75 Create a digest over the entire packet (including the data), and
76 MD5 it with the session key.
77 ********************************************************************/
78 static void schannel_digest(const uint8_t sess_key[16],
/* [<][>][^][v][top][bottom][index][help] */
79 const uint8_t netsec_sig[8],
80 const uint8_t *confounder,
81 const uint8_t *data, size_t data_len,
82 uint8_t digest_final[16])
83 {
84 uint8_t packet_digest[16];
85 static const uint8_t zeros[4];
86 struct MD5Context ctx;
87
88 MD5Init(&ctx);
89 MD5Update(&ctx, zeros, 4);
90 MD5Update(&ctx, netsec_sig, 8);
91 if (confounder) {
92 MD5Update(&ctx, confounder, 8);
93 }
94 MD5Update(&ctx, data, data_len);
95 MD5Final(packet_digest, &ctx);
96
97 hmac_md5(sess_key, packet_digest, sizeof(packet_digest), digest_final);
98 }
99
100
101 /*
102 unseal a packet
103 */
104 NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
105 TALLOC_CTX *mem_ctx,
106 uint8_t *data, size_t length,
107 const uint8_t *whole_pdu, size_t pdu_length,
108 const DATA_BLOB *sig)
109 {
110 struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
111
112 uint8_t digest_final[16];
113 uint8_t confounder[8];
114 uint8_t seq_num[8];
115 uint8_t sealing_key[16];
116 static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
117
118 if (sig->length != 32) {
119 return NT_STATUS_ACCESS_DENIED;
120 }
121
122 memcpy(confounder, sig->data+24, 8);
123
124 RSIVAL(seq_num, 0, state->seq_num);
125 SIVAL(seq_num, 4, state->initiator?0:0x80);
126
127 netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
128 arcfour_crypt(confounder, sealing_key, 8);
129 arcfour_crypt(data, sealing_key, length);
130
131 schannel_digest(state->creds->session_key,
132 netsec_sig, confounder,
133 data, length, digest_final);
134
135 if (memcmp(digest_final, sig->data+16, 8) != 0) {
136 dump_data_pw("calc digest:", digest_final, 8);
137 dump_data_pw("wire digest:", sig->data+16, 8);
138 return NT_STATUS_ACCESS_DENIED;
139 }
140
141 netsec_deal_with_seq_num(state, digest_final, seq_num);
142
143 if (memcmp(seq_num, sig->data+8, 8) != 0) {
144 dump_data_pw("calc seq num:", seq_num, 8);
145 dump_data_pw("wire seq num:", sig->data+8, 8);
146 return NT_STATUS_ACCESS_DENIED;
147 }
148
149 return NT_STATUS_OK;
150 }
151
152 /*
153 check the signature on a packet
154 */
155 NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
156 TALLOC_CTX *mem_ctx,
157 const uint8_t *data, size_t length,
158 const uint8_t *whole_pdu, size_t pdu_length,
159 const DATA_BLOB *sig)
160 {
161 struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
162
163 uint8_t digest_final[16];
164 uint8_t seq_num[8];
165 static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
166
167 /* w2k sends just 24 bytes and skip the confounder */
168 if (sig->length != 32 && sig->length != 24) {
169 return NT_STATUS_ACCESS_DENIED;
170 }
171
172 RSIVAL(seq_num, 0, state->seq_num);
173 SIVAL(seq_num, 4, state->initiator?0:0x80);
174
175 dump_data_pw("seq_num:\n", seq_num, 8);
176 dump_data_pw("sess_key:\n", state->creds->session_key, 16);
177
178 schannel_digest(state->creds->session_key,
179 netsec_sig, NULL,
180 data, length, digest_final);
181
182 netsec_deal_with_seq_num(state, digest_final, seq_num);
183
184 if (memcmp(seq_num, sig->data+8, 8) != 0) {
185 dump_data_pw("calc seq num:", seq_num, 8);
186 dump_data_pw("wire seq num:", sig->data+8, 8);
187 return NT_STATUS_ACCESS_DENIED;
188 }
189
190 if (memcmp(digest_final, sig->data+16, 8) != 0) {
191 dump_data_pw("calc digest:", digest_final, 8);
192 dump_data_pw("wire digest:", sig->data+16, 8);
193 return NT_STATUS_ACCESS_DENIED;
194 }
195
196 return NT_STATUS_OK;
197 }
198
199
200 /*
201 seal a packet
202 */
203 NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
204 TALLOC_CTX *mem_ctx,
205 uint8_t *data, size_t length,
206 const uint8_t *whole_pdu, size_t pdu_length,
207 DATA_BLOB *sig)
208 {
209 struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
210
211 uint8_t digest_final[16];
212 uint8_t confounder[8];
213 uint8_t seq_num[8];
214 uint8_t sealing_key[16];
215 static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
216
217 generate_random_buffer(confounder, 8);
218
219 RSIVAL(seq_num, 0, state->seq_num);
220 SIVAL(seq_num, 4, state->initiator?0x80:0);
221
222 schannel_digest(state->creds->session_key,
223 netsec_sig, confounder,
224 data, length, digest_final);
225
226 netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
227 arcfour_crypt(confounder, sealing_key, 8);
228 arcfour_crypt(data, sealing_key, length);
229
230 netsec_deal_with_seq_num(state, digest_final, seq_num);
231
232 (*sig) = data_blob_talloc(mem_ctx, NULL, 32);
233
234 memcpy(sig->data, netsec_sig, 8);
235 memcpy(sig->data+8, seq_num, 8);
236 memcpy(sig->data+16, digest_final, 8);
237 memcpy(sig->data+24, confounder, 8);
238
239 dump_data_pw("signature:", sig->data+ 0, 8);
240 dump_data_pw("seq_num :", sig->data+ 8, 8);
241 dump_data_pw("digest :", sig->data+16, 8);
242 dump_data_pw("confound :", sig->data+24, 8);
243
244 return NT_STATUS_OK;
245 }
246
247
248 /*
249 sign a packet
250 */
251 NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
252 TALLOC_CTX *mem_ctx,
253 const uint8_t *data, size_t length,
254 const uint8_t *whole_pdu, size_t pdu_length,
255 DATA_BLOB *sig)
256 {
257 struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
258
259 uint8_t digest_final[16];
260 uint8_t seq_num[8];
261 static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
262
263 RSIVAL(seq_num, 0, state->seq_num);
264 SIVAL(seq_num, 4, state->initiator?0x80:0);
265
266 schannel_digest(state->creds->session_key,
267 netsec_sig, NULL,
268 data, length, digest_final);
269
270 netsec_deal_with_seq_num(state, digest_final, seq_num);
271
272 (*sig) = data_blob_talloc(mem_ctx, NULL, 32);
273
274 memcpy(sig->data, netsec_sig, 8);
275 memcpy(sig->data+8, seq_num, 8);
276 memcpy(sig->data+16, digest_final, 8);
277 memset(sig->data+24, 0, 8);
278
279 dump_data_pw("signature:", sig->data+ 0, 8);
280 dump_data_pw("seq_num :", sig->data+ 8, 8);
281 dump_data_pw("digest :", sig->data+16, 8);
282 dump_data_pw("confound :", sig->data+24, 8);
283
284 return NT_STATUS_OK;
285 }