2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "gssapi_locl.h"
36 RCSID("$Id: verify_mic.c,v 1.18.2.4 2003/09/18 22:05:34 lha Exp $");
40 (OM_uint32 * minor_status,
41 const gss_ctx_id_t context_handle,
42 const gss_buffer_t message_buffer,
43 const gss_buffer_t token_buffer,
44 gss_qop_t * qop_state,
51 u_char hash[16], seq_data[8];
52 des_key_schedule schedule;
58 p = token_buffer->value;
59 ret = gssapi_krb5_verify_header (&p,
65 if (memcmp(p, "\x00\x00", 2) != 0)
68 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
75 MD5_Update (&md5, p - 24, 8);
76 MD5_Update (&md5, message_buffer->value,
77 message_buffer->length);
78 MD5_Final (hash, &md5);
80 memset (&zero, 0, sizeof(zero));
81 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
83 des_set_key (&deskey, schedule);
84 des_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
86 if (memcmp (p - 8, hash, 8) != 0) {
87 memset (deskey, 0, sizeof(deskey));
88 memset (schedule, 0, sizeof(schedule));
92 /* verify sequence number */
94 krb5_auth_getremoteseqnumber (gssapi_krb5_context,
95 context_handle->auth_context,
97 seq_data[0] = (seq_number >> 0) & 0xFF;
98 seq_data[1] = (seq_number >> 8) & 0xFF;
99 seq_data[2] = (seq_number >> 16) & 0xFF;
100 seq_data[3] = (seq_number >> 24) & 0xFF;
101 memset (seq_data + 4,
102 (context_handle->more_flags & LOCAL) ? 0xFF : 0,
106 des_set_key (&deskey, schedule);
107 des_cbc_encrypt ((void *)p, (void *)p, 8,
108 schedule, (des_cblock *)hash, DES_DECRYPT);
110 memset (deskey, 0, sizeof(deskey));
111 memset (schedule, 0, sizeof(schedule));
113 if (memcmp (p, seq_data, 8) != 0) {
114 return GSS_S_BAD_MIC;
117 krb5_auth_con_setremoteseqnumber (gssapi_krb5_context,
118 context_handle->auth_context,
121 return GSS_S_COMPLETE;
126 (OM_uint32 * minor_status,
127 const gss_ctx_id_t context_handle,
128 const gss_buffer_t message_buffer,
129 const gss_buffer_t token_buffer,
130 gss_qop_t * qop_state,
146 p = token_buffer->value;
147 ret = gssapi_krb5_verify_header (&p,
148 token_buffer->length,
153 if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */
154 return GSS_S_BAD_SIG;
156 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
157 return GSS_S_BAD_MIC;
160 ret = krb5_crypto_init(gssapi_krb5_context, key,
161 ETYPE_DES3_CBC_NONE, &crypto);
163 gssapi_krb5_set_error_string ();
165 return GSS_S_FAILURE;
168 /* verify sequence number */
174 memcpy(ivec, p + 8, 8);
176 ret = krb5_decrypt_ivec (gssapi_krb5_context,
179 p, 8, &seq_data, ivec);
182 gssapi_krb5_set_error_string ();
183 krb5_crypto_destroy (gssapi_krb5_context, crypto);
185 return GSS_S_FAILURE;
190 if (seq_data.length != 8) {
191 krb5_data_free (&seq_data);
193 krb5_crypto_destroy (gssapi_krb5_context, crypto);
194 return GSS_S_BAD_MIC;
199 krb5_auth_getremoteseqnumber (gssapi_krb5_context,
200 context_handle->auth_context,
202 seq[0] = (seq_number >> 0) & 0xFF;
203 seq[1] = (seq_number >> 8) & 0xFF;
204 seq[2] = (seq_number >> 16) & 0xFF;
205 seq[3] = (seq_number >> 24) & 0xFF;
207 (context_handle->more_flags & LOCAL) ? 0xFF : 0,
209 cmp = memcmp (seq, seq_data.data, seq_data.length);
210 krb5_data_free (&seq_data);
213 krb5_crypto_destroy (gssapi_krb5_context, crypto);
214 return GSS_S_BAD_MIC;
219 /* verify checksum */
221 tmp = malloc (message_buffer->length + 8);
223 krb5_crypto_destroy (gssapi_krb5_context, crypto);
224 *minor_status = ENOMEM;
225 return GSS_S_FAILURE;
228 memcpy (tmp, p - 8, 8);
229 memcpy (tmp + 8, message_buffer->value, message_buffer->length);
231 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
232 csum.checksum.length = 20;
233 csum.checksum.data = p + 8;
235 ret = krb5_verify_checksum (gssapi_krb5_context, crypto,
237 tmp, message_buffer->length + 8,
241 gssapi_krb5_set_error_string ();
242 krb5_crypto_destroy (gssapi_krb5_context, crypto);
244 return GSS_S_BAD_MIC;
247 krb5_auth_con_setremoteseqnumber (gssapi_krb5_context,
248 context_handle->auth_context,
251 krb5_crypto_destroy (gssapi_krb5_context, crypto);
252 return GSS_S_COMPLETE;
256 gss_verify_mic_internal
257 (OM_uint32 * minor_status,
258 const gss_ctx_id_t context_handle,
259 const gss_buffer_t message_buffer,
260 const gss_buffer_t token_buffer,
261 gss_qop_t * qop_state,
267 krb5_keytype keytype;
269 ret = gss_krb5_get_remotekey(context_handle, &key);
271 gssapi_krb5_set_error_string ();
273 return GSS_S_FAILURE;
276 krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
279 ret = verify_mic_des (minor_status, context_handle,
280 message_buffer, token_buffer, qop_state, key,
284 ret = verify_mic_des3 (minor_status, context_handle,
285 message_buffer, token_buffer, qop_state, key,
288 case KEYTYPE_ARCFOUR :
289 ret = _gssapi_verify_mic_arcfour (minor_status, context_handle,
290 message_buffer, token_buffer,
291 qop_state, key, type);
294 *minor_status = KRB5_PROG_ETYPE_NOSUPP;
298 krb5_free_keyblock (gssapi_krb5_context, key);
305 (OM_uint32 * minor_status,
306 const gss_ctx_id_t context_handle,
307 const gss_buffer_t message_buffer,
308 const gss_buffer_t token_buffer,
309 gss_qop_t * qop_state
314 if (qop_state != NULL)
315 *qop_state = GSS_C_QOP_DEFAULT;
317 ret = gss_verify_mic_internal(minor_status, context_handle,
318 message_buffer, token_buffer,
319 qop_state, "\x01\x01");