Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "gsskrb5_locl.h"
35 :
36 : #ifdef HEIM_WEAK_CRYPTO
37 :
38 : static OM_uint32
39 : mic_des
40 : (OM_uint32 * minor_status,
41 : const gsskrb5_ctx ctx,
42 : krb5_context context,
43 : gss_qop_t qop_req,
44 : const gss_buffer_t message_buffer,
45 : gss_buffer_t message_token,
46 : krb5_keyblock *key
47 : )
48 : {
49 : u_char *p;
50 : EVP_MD_CTX *md5;
51 : u_char hash[16];
52 : DES_key_schedule schedule;
53 : EVP_CIPHER_CTX des_ctx;
54 : DES_cblock deskey;
55 : DES_cblock zero;
56 : int32_t seq_number;
57 : size_t len, total_len;
58 :
59 : _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
60 :
61 : message_token->length = total_len;
62 : message_token->value = malloc (total_len);
63 : if (message_token->value == NULL) {
64 : message_token->length = 0;
65 : *minor_status = ENOMEM;
66 : return GSS_S_FAILURE;
67 : }
68 :
69 : p = _gsskrb5_make_header(message_token->value,
70 : len,
71 : "\x01\x01", /* TOK_ID */
72 : GSS_KRB5_MECHANISM);
73 :
74 : memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */
75 : p += 2;
76 :
77 : memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */
78 : p += 4;
79 :
80 : /* Fill in later (SND-SEQ) */
81 : memset (p, 0, 16);
82 : p += 16;
83 :
84 : /* checksum */
85 : md5 = EVP_MD_CTX_create();
86 : EVP_DigestInit_ex(md5, EVP_md5(), NULL);
87 : EVP_DigestUpdate(md5, p - 24, 8);
88 : EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length);
89 : EVP_DigestFinal_ex(md5, hash, NULL);
90 : EVP_MD_CTX_destroy(md5);
91 :
92 : memset (&zero, 0, sizeof(zero));
93 : memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
94 : DES_set_key_unchecked (&deskey, &schedule);
95 : DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
96 : &schedule, &zero);
97 : memcpy (p - 8, hash, 8); /* SGN_CKSUM */
98 :
99 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
100 : /* sequence number */
101 : krb5_auth_con_getlocalseqnumber (context,
102 : ctx->auth_context,
103 : &seq_number);
104 :
105 : p -= 16; /* SND_SEQ */
106 : p[0] = (seq_number >> 0) & 0xFF;
107 : p[1] = (seq_number >> 8) & 0xFF;
108 : p[2] = (seq_number >> 16) & 0xFF;
109 : p[3] = (seq_number >> 24) & 0xFF;
110 : memset (p + 4,
111 : (ctx->more_flags & LOCAL) ? 0 : 0xFF,
112 : 4);
113 :
114 : EVP_CIPHER_CTX_init(&des_ctx);
115 : EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1);
116 : EVP_Cipher(&des_ctx, p, p, 8);
117 : EVP_CIPHER_CTX_cleanup(&des_ctx);
118 :
119 : krb5_auth_con_setlocalseqnumber (context,
120 : ctx->auth_context,
121 : ++seq_number);
122 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
123 :
124 : memset_s(deskey, sizeof(deskey), 0, sizeof(deskey));
125 : memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule));
126 :
127 : *minor_status = 0;
128 : return GSS_S_COMPLETE;
129 : }
130 : #endif
131 :
132 : static OM_uint32
133 0 : mic_des3
134 : (OM_uint32 * minor_status,
135 : const gsskrb5_ctx ctx,
136 : krb5_context context,
137 : gss_qop_t qop_req,
138 : const gss_buffer_t message_buffer,
139 : gss_buffer_t message_token,
140 : krb5_keyblock *key
141 : )
142 : {
143 0 : u_char *p;
144 0 : Checksum cksum;
145 0 : u_char seq[8];
146 :
147 0 : int32_t seq_number;
148 0 : size_t len, total_len;
149 :
150 0 : krb5_crypto crypto;
151 0 : krb5_error_code kret;
152 0 : krb5_data encdata;
153 0 : char *tmp;
154 0 : char ivec[8];
155 :
156 0 : _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM);
157 :
158 0 : message_token->length = total_len;
159 0 : message_token->value = malloc (total_len);
160 0 : if (message_token->value == NULL) {
161 0 : message_token->length = 0;
162 0 : *minor_status = ENOMEM;
163 0 : return GSS_S_FAILURE;
164 : }
165 :
166 0 : p = _gsskrb5_make_header(message_token->value,
167 : len,
168 : "\x01\x01", /* TOK-ID */
169 : GSS_KRB5_MECHANISM);
170 :
171 0 : memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */
172 0 : p += 2;
173 :
174 0 : memcpy (p, "\xff\xff\xff\xff", 4); /* filler */
175 0 : p += 4;
176 :
177 : /* this should be done in parts */
178 :
179 0 : tmp = malloc (message_buffer->length + 8);
180 0 : if (tmp == NULL) {
181 0 : free (message_token->value);
182 0 : message_token->value = NULL;
183 0 : message_token->length = 0;
184 0 : *minor_status = ENOMEM;
185 0 : return GSS_S_FAILURE;
186 : }
187 0 : memcpy (tmp, p - 8, 8);
188 0 : memcpy (tmp + 8, message_buffer->value, message_buffer->length);
189 :
190 0 : kret = krb5_crypto_init(context, key, 0, &crypto);
191 0 : if (kret) {
192 0 : free (message_token->value);
193 0 : message_token->value = NULL;
194 0 : message_token->length = 0;
195 0 : free (tmp);
196 0 : *minor_status = kret;
197 0 : return GSS_S_FAILURE;
198 : }
199 :
200 0 : kret = krb5_create_checksum (context,
201 : crypto,
202 : KRB5_KU_USAGE_SIGN,
203 : 0,
204 : tmp,
205 0 : message_buffer->length + 8,
206 : &cksum);
207 0 : free (tmp);
208 0 : krb5_crypto_destroy (context, crypto);
209 0 : if (kret) {
210 0 : free (message_token->value);
211 0 : message_token->value = NULL;
212 0 : message_token->length = 0;
213 0 : *minor_status = kret;
214 0 : return GSS_S_FAILURE;
215 : }
216 :
217 0 : memcpy (p + 8, cksum.checksum.data, cksum.checksum.length);
218 :
219 0 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
220 : /* sequence number */
221 0 : krb5_auth_con_getlocalseqnumber (context,
222 : ctx->auth_context,
223 : &seq_number);
224 :
225 0 : seq[0] = (seq_number >> 0) & 0xFF;
226 0 : seq[1] = (seq_number >> 8) & 0xFF;
227 0 : seq[2] = (seq_number >> 16) & 0xFF;
228 0 : seq[3] = (seq_number >> 24) & 0xFF;
229 0 : memset (seq + 4,
230 0 : (ctx->more_flags & LOCAL) ? 0 : 0xFF,
231 : 4);
232 :
233 0 : kret = krb5_crypto_init(context, key,
234 : ETYPE_DES3_CBC_NONE, &crypto);
235 0 : if (kret) {
236 0 : free (message_token->value);
237 0 : message_token->value = NULL;
238 0 : message_token->length = 0;
239 0 : *minor_status = kret;
240 0 : return GSS_S_FAILURE;
241 : }
242 :
243 0 : if (ctx->more_flags & COMPAT_OLD_DES3)
244 0 : memset(ivec, 0, 8);
245 : else
246 0 : memcpy(ivec, p + 8, 8);
247 :
248 0 : kret = krb5_encrypt_ivec (context,
249 : crypto,
250 : KRB5_KU_USAGE_SEQ,
251 : seq, 8, &encdata, ivec);
252 0 : krb5_crypto_destroy (context, crypto);
253 0 : if (kret) {
254 0 : free (message_token->value);
255 0 : message_token->value = NULL;
256 0 : message_token->length = 0;
257 0 : *minor_status = kret;
258 0 : return GSS_S_FAILURE;
259 : }
260 :
261 0 : assert (encdata.length == 8);
262 :
263 0 : memcpy (p, encdata.data, encdata.length);
264 0 : krb5_data_free (&encdata);
265 :
266 0 : krb5_auth_con_setlocalseqnumber (context,
267 : ctx->auth_context,
268 : ++seq_number);
269 0 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
270 :
271 0 : free_Checksum (&cksum);
272 0 : *minor_status = 0;
273 0 : return GSS_S_COMPLETE;
274 : }
275 :
276 251509 : OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic
277 : (OM_uint32 * minor_status,
278 : gss_const_ctx_id_t context_handle,
279 : gss_qop_t qop_req,
280 : const gss_buffer_t message_buffer,
281 : gss_buffer_t message_token
282 : )
283 : {
284 317 : krb5_context context;
285 251509 : const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
286 317 : krb5_keyblock *key;
287 317 : OM_uint32 ret;
288 :
289 251509 : GSSAPI_KRB5_INIT (&context);
290 :
291 251509 : if (ctx->more_flags & IS_CFX)
292 236340 : return _gssapi_mic_cfx (minor_status, ctx, context, qop_req,
293 : message_buffer, message_token);
294 :
295 0 : HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
296 15169 : ret = _gsskrb5i_get_token_key(ctx, context, &key);
297 0 : HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
298 15169 : if (ret) {
299 0 : *minor_status = ret;
300 0 : return GSS_S_FAILURE;
301 : }
302 :
303 15169 : switch (key->keytype) {
304 0 : case KRB5_ENCTYPE_DES_CBC_CRC :
305 : case KRB5_ENCTYPE_DES_CBC_MD4 :
306 : case KRB5_ENCTYPE_DES_CBC_MD5 :
307 : #ifdef HEIM_WEAK_CRYPTO
308 : ret = mic_des (minor_status, ctx, context, qop_req,
309 : message_buffer, message_token, key);
310 : #else
311 0 : ret = GSS_S_FAILURE;
312 : #endif
313 0 : break;
314 0 : case KRB5_ENCTYPE_DES3_CBC_MD5 :
315 : case KRB5_ENCTYPE_DES3_CBC_SHA1 :
316 0 : ret = mic_des3 (minor_status, ctx, context, qop_req,
317 : message_buffer, message_token, key);
318 0 : break;
319 15169 : case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5:
320 : case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56:
321 15169 : ret = _gssapi_get_mic_arcfour (minor_status, ctx, context, qop_req,
322 : message_buffer, message_token, key);
323 15169 : break;
324 0 : default :
325 0 : abort();
326 0 : break;
327 : }
328 15169 : krb5_free_keyblock (context, key);
329 15169 : return ret;
330 : }
|