Pre-2.0 release, MFC firewire disk changes to properly detach SIMs.
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / gssapi / verify_mic.c
blobaef2d07da6bf3325d94f84d8141ba925118ad260
1 /*
2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "gssapi_locl.h"
36 RCSID("$Id: verify_mic.c,v 1.18.2.4 2003/09/18 22:05:34 lha Exp $");
38 static OM_uint32
39 verify_mic_des
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,
45 krb5_keyblock *key,
46 char *type
49 u_char *p;
50 MD5_CTX md5;
51 u_char hash[16], seq_data[8];
52 des_key_schedule schedule;
53 des_cblock zero;
54 des_cblock deskey;
55 int32_t seq_number;
56 OM_uint32 ret;
58 p = token_buffer->value;
59 ret = gssapi_krb5_verify_header (&p,
60 token_buffer->length,
61 type);
62 if (ret)
63 return ret;
65 if (memcmp(p, "\x00\x00", 2) != 0)
66 return GSS_S_BAD_SIG;
67 p += 2;
68 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
69 return GSS_S_BAD_MIC;
70 p += 4;
71 p += 16;
73 /* verify checksum */
74 MD5_Init (&md5);
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),
85 schedule, &zero);
86 if (memcmp (p - 8, hash, 8) != 0) {
87 memset (deskey, 0, sizeof(deskey));
88 memset (schedule, 0, sizeof(schedule));
89 return GSS_S_BAD_MIC;
92 /* verify sequence number */
94 krb5_auth_getremoteseqnumber (gssapi_krb5_context,
95 context_handle->auth_context,
96 &seq_number);
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,
105 p -= 16;
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,
119 ++seq_number);
121 return GSS_S_COMPLETE;
124 static OM_uint32
125 verify_mic_des3
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,
131 krb5_keyblock *key,
132 char *type
135 u_char *p;
136 u_char seq[8];
137 int32_t seq_number;
138 OM_uint32 ret;
139 krb5_crypto crypto;
140 krb5_data seq_data;
141 int cmp, docompat;
142 Checksum csum;
143 char *tmp;
144 char ivec[8];
146 p = token_buffer->value;
147 ret = gssapi_krb5_verify_header (&p,
148 token_buffer->length,
149 type);
150 if (ret)
151 return ret;
153 if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */
154 return GSS_S_BAD_SIG;
155 p += 2;
156 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
157 return GSS_S_BAD_MIC;
158 p += 4;
160 ret = krb5_crypto_init(gssapi_krb5_context, key,
161 ETYPE_DES3_CBC_NONE, &crypto);
162 if (ret){
163 gssapi_krb5_set_error_string ();
164 *minor_status = ret;
165 return GSS_S_FAILURE;
168 /* verify sequence number */
169 docompat = 0;
170 retry:
171 if (docompat)
172 memset(ivec, 0, 8);
173 else
174 memcpy(ivec, p + 8, 8);
176 ret = krb5_decrypt_ivec (gssapi_krb5_context,
177 crypto,
178 KRB5_KU_USAGE_SEQ,
179 p, 8, &seq_data, ivec);
180 if (ret) {
181 if (docompat++) {
182 gssapi_krb5_set_error_string ();
183 krb5_crypto_destroy (gssapi_krb5_context, crypto);
184 *minor_status = ret;
185 return GSS_S_FAILURE;
186 } else
187 goto retry;
190 if (seq_data.length != 8) {
191 krb5_data_free (&seq_data);
192 if (docompat++) {
193 krb5_crypto_destroy (gssapi_krb5_context, crypto);
194 return GSS_S_BAD_MIC;
195 } else
196 goto retry;
199 krb5_auth_getremoteseqnumber (gssapi_krb5_context,
200 context_handle->auth_context,
201 &seq_number);
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;
206 memset (seq + 4,
207 (context_handle->more_flags & LOCAL) ? 0xFF : 0,
209 cmp = memcmp (seq, seq_data.data, seq_data.length);
210 krb5_data_free (&seq_data);
211 if (cmp != 0) {
212 if (docompat++) {
213 krb5_crypto_destroy (gssapi_krb5_context, crypto);
214 return GSS_S_BAD_MIC;
215 } else
216 goto retry;
219 /* verify checksum */
221 tmp = malloc (message_buffer->length + 8);
222 if (tmp == NULL) {
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,
236 KRB5_KU_USAGE_SIGN,
237 tmp, message_buffer->length + 8,
238 &csum);
239 free (tmp);
240 if (ret) {
241 gssapi_krb5_set_error_string ();
242 krb5_crypto_destroy (gssapi_krb5_context, crypto);
243 *minor_status = ret;
244 return GSS_S_BAD_MIC;
247 krb5_auth_con_setremoteseqnumber (gssapi_krb5_context,
248 context_handle->auth_context,
249 ++seq_number);
251 krb5_crypto_destroy (gssapi_krb5_context, crypto);
252 return GSS_S_COMPLETE;
255 OM_uint32
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,
262 char * type
265 krb5_keyblock *key;
266 OM_uint32 ret;
267 krb5_keytype keytype;
269 ret = gss_krb5_get_remotekey(context_handle, &key);
270 if (ret) {
271 gssapi_krb5_set_error_string ();
272 *minor_status = ret;
273 return GSS_S_FAILURE;
275 *minor_status = 0;
276 krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
277 switch (keytype) {
278 case KEYTYPE_DES :
279 ret = verify_mic_des (minor_status, context_handle,
280 message_buffer, token_buffer, qop_state, key,
281 type);
282 break;
283 case KEYTYPE_DES3 :
284 ret = verify_mic_des3 (minor_status, context_handle,
285 message_buffer, token_buffer, qop_state, key,
286 type);
287 break;
288 case KEYTYPE_ARCFOUR :
289 ret = _gssapi_verify_mic_arcfour (minor_status, context_handle,
290 message_buffer, token_buffer,
291 qop_state, key, type);
292 break;
293 default :
294 *minor_status = KRB5_PROG_ETYPE_NOSUPP;
295 ret = GSS_S_FAILURE;
296 break;
298 krb5_free_keyblock (gssapi_krb5_context, key);
300 return ret;
303 OM_uint32
304 gss_verify_mic
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
312 OM_uint32 ret;
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");
321 return ret;