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 "../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"
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 }
34
/*******************************************************************
35
Encode or Decode the sequence number (which is symmetric)
36
********************************************************************/
37
static void netsec_deal_with_seq_num(struct schannel_state *state,
38
const uint8_t packet_digest[8],
41
static const uint8_t zeros[4];
42
uint8_t sequence_key[16];
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);
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],
57
const uint8_t seq_num[8],
58
uint8_t sealing_key[16])
60
static const uint8_t zeros[4];
65
for (i = 0; i < 16; i++) {
66
sess_kf0[i] = session_key[i] ^ 0xf0;
69
hmac_md5(sess_kf0, zeros, 4, digest2);
70
hmac_md5(digest2, seq_num, 8, sealing_key);
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],
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])
84
uint8_t packet_digest[16];
85
static const uint8_t zeros[4];
86
struct MD5Context ctx;
89
MD5Update(&ctx, zeros, 4);
90
MD5Update(&ctx, netsec_sig, 8);
92
MD5Update(&ctx, confounder, 8);
94
MD5Update(&ctx, data, data_len);
95
MD5Final(packet_digest, &ctx);
97
hmac_md5(sess_key, packet_digest, sizeof(packet_digest), digest_final);
104
NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
106
uint8_t *data, size_t length,
107
const uint8_t *whole_pdu, size_t pdu_length,
108
const DATA_BLOB *sig)
110
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
112
uint8_t digest_final[16];
113
uint8_t confounder[8];
115
uint8_t sealing_key[16];
116
static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
118
if (sig->length != 32) {
119
return NT_STATUS_ACCESS_DENIED;
122
memcpy(confounder, sig->data+24, 8);
124
RSIVAL(seq_num, 0, state->seq_num);
125
SIVAL(seq_num, 4, state->initiator?0:0x80);
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);
131
schannel_digest(state->creds->session_key,
132
netsec_sig, confounder,
133
data, length, digest_final);
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;
141
netsec_deal_with_seq_num(state, digest_final, seq_num);
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;
153
check the signature on a packet
155
NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
157
const uint8_t *data, size_t length,
158
const uint8_t *whole_pdu, size_t pdu_length,
159
const DATA_BLOB *sig)
161
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
163
uint8_t digest_final[16];
165
static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
167
/* w2k sends just 24 bytes and skip the confounder */
168
if (sig->length != 32 && sig->length != 24) {
169
return NT_STATUS_ACCESS_DENIED;
172
RSIVAL(seq_num, 0, state->seq_num);
173
SIVAL(seq_num, 4, state->initiator?0:0x80);
175
dump_data_pw("seq_num:\n", seq_num, 8);
176
dump_data_pw("sess_key:\n", state->creds->session_key, 16);
178
schannel_digest(state->creds->session_key,
180
data, length, digest_final);
182
netsec_deal_with_seq_num(state, digest_final, seq_num);
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;
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;
203
NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
205
uint8_t *data, size_t length,
206
const uint8_t *whole_pdu, size_t pdu_length,
209
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
211
uint8_t digest_final[16];
212
uint8_t confounder[8];
214
uint8_t sealing_key[16];
215
static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
217
generate_random_buffer(confounder, 8);
219
RSIVAL(seq_num, 0, state->seq_num);
220
SIVAL(seq_num, 4, state->initiator?0x80:0);
222
schannel_digest(state->creds->session_key,
223
netsec_sig, confounder,
224
data, length, digest_final);
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);
230
netsec_deal_with_seq_num(state, digest_final, seq_num);
232
(*sig) = data_blob_talloc(mem_ctx, NULL, 32);
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);
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);
251
NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
253
const uint8_t *data, size_t length,
254
const uint8_t *whole_pdu, size_t pdu_length,
257
struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state);
259
uint8_t digest_final[16];
261
static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
263
RSIVAL(seq_num, 0, state->seq_num);
264
SIVAL(seq_num, 4, state->initiator?0x80:0);
266
schannel_digest(state->creds->session_key,
268
data, length, digest_final);
270
netsec_deal_with_seq_num(state, digest_final, seq_num);
272
(*sig) = data_blob_talloc(mem_ctx, NULL, 32);
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);
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);