switch to use EVP interface instead of old crypto interface
[heimdal.git] / lib / gssapi / krb5 / verify_mic.c
bloba59eb6239ee2482924d49e23c9fb2d395074d846
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 "gsskrb5_locl.h"
36 static OM_uint32
37 verify_mic_des
38 (OM_uint32 * minor_status,
39 const gsskrb5_ctx context_handle,
40 krb5_context context,
41 const gss_buffer_t message_buffer,
42 const gss_buffer_t token_buffer,
43 gss_qop_t * qop_state,
44 krb5_keyblock *key,
45 char *type
48 u_char *p;
49 EVP_MD_CTX md5;
50 u_char hash[16], *seq;
51 DES_key_schedule schedule;
52 EVP_CIPHER_CTX des_ctx;
53 DES_cblock zero;
54 DES_cblock deskey;
55 uint32_t seq_number;
56 OM_uint32 ret;
57 int cmp;
59 p = token_buffer->value;
60 ret = _gsskrb5_verify_header (&p,
61 token_buffer->length,
62 type,
63 GSS_KRB5_MECHANISM);
64 if (ret)
65 return ret;
67 if (memcmp(p, "\x00\x00", 2) != 0)
68 return GSS_S_BAD_SIG;
69 p += 2;
70 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
71 return GSS_S_BAD_MIC;
72 p += 4;
73 p += 16;
75 /* verify checksum */
76 EVP_MD_CTX_init(&md5);
77 EVP_DigestInit_ex(&md5, EVP_md5(), NULL);
78 EVP_DigestUpdate(&md5, p - 24, 8);
79 EVP_DigestUpdate(&md5, message_buffer->value, message_buffer->length);
80 EVP_DigestFinal_ex(&md5, hash, NULL);
81 EVP_MD_CTX_cleanup(&md5);
83 memset (&zero, 0, sizeof(zero));
84 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
86 DES_set_key_unchecked (&deskey, &schedule);
87 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
88 &schedule, &zero);
89 if (ct_memcmp (p - 8, hash, 8) != 0) {
90 memset (deskey, 0, sizeof(deskey));
91 memset (&schedule, 0, sizeof(schedule));
92 return GSS_S_BAD_MIC;
95 /* verify sequence number */
97 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
99 p -= 16;
101 EVP_CIPHER_CTX_init(&des_ctx);
102 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
103 EVP_Cipher(&des_ctx, p, p, 8);
104 EVP_CIPHER_CTX_cleanup(&des_ctx);
106 memset (deskey, 0, sizeof(deskey));
107 memset (&schedule, 0, sizeof(schedule));
109 seq = p;
110 _gsskrb5_decode_om_uint32(seq, &seq_number);
112 if (context_handle->more_flags & LOCAL)
113 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
114 else
115 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
117 if (cmp != 0) {
118 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
119 return GSS_S_BAD_MIC;
122 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
123 if (ret) {
124 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
125 return ret;
128 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
130 return GSS_S_COMPLETE;
133 static OM_uint32
134 verify_mic_des3
135 (OM_uint32 * minor_status,
136 const gsskrb5_ctx context_handle,
137 krb5_context context,
138 const gss_buffer_t message_buffer,
139 const gss_buffer_t token_buffer,
140 gss_qop_t * qop_state,
141 krb5_keyblock *key,
142 char *type
145 u_char *p;
146 u_char *seq;
147 uint32_t seq_number;
148 OM_uint32 ret;
149 krb5_crypto crypto;
150 krb5_data seq_data;
151 int cmp, docompat;
152 Checksum csum;
153 char *tmp;
154 char ivec[8];
156 p = token_buffer->value;
157 ret = _gsskrb5_verify_header (&p,
158 token_buffer->length,
159 type,
160 GSS_KRB5_MECHANISM);
161 if (ret)
162 return ret;
164 if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */
165 return GSS_S_BAD_SIG;
166 p += 2;
167 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
168 return GSS_S_BAD_MIC;
169 p += 4;
171 ret = krb5_crypto_init(context, key,
172 ETYPE_DES3_CBC_NONE, &crypto);
173 if (ret){
174 *minor_status = ret;
175 return GSS_S_FAILURE;
178 /* verify sequence number */
179 docompat = 0;
180 retry:
181 if (docompat)
182 memset(ivec, 0, 8);
183 else
184 memcpy(ivec, p + 8, 8);
186 ret = krb5_decrypt_ivec (context,
187 crypto,
188 KRB5_KU_USAGE_SEQ,
189 p, 8, &seq_data, ivec);
190 if (ret) {
191 if (docompat++) {
192 krb5_crypto_destroy (context, crypto);
193 *minor_status = ret;
194 return GSS_S_FAILURE;
195 } else
196 goto retry;
199 if (seq_data.length != 8) {
200 krb5_data_free (&seq_data);
201 if (docompat++) {
202 krb5_crypto_destroy (context, crypto);
203 return GSS_S_BAD_MIC;
204 } else
205 goto retry;
208 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
210 seq = seq_data.data;
211 _gsskrb5_decode_om_uint32(seq, &seq_number);
213 if (context_handle->more_flags & LOCAL)
214 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
215 else
216 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
218 krb5_data_free (&seq_data);
219 if (cmp != 0) {
220 krb5_crypto_destroy (context, crypto);
221 *minor_status = 0;
222 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
223 return GSS_S_BAD_MIC;
226 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
227 if (ret) {
228 krb5_crypto_destroy (context, crypto);
229 *minor_status = 0;
230 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
231 return ret;
234 /* verify checksum */
236 tmp = malloc (message_buffer->length + 8);
237 if (tmp == NULL) {
238 krb5_crypto_destroy (context, crypto);
239 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
240 *minor_status = ENOMEM;
241 return GSS_S_FAILURE;
244 memcpy (tmp, p - 8, 8);
245 memcpy (tmp + 8, message_buffer->value, message_buffer->length);
247 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
248 csum.checksum.length = 20;
249 csum.checksum.data = p + 8;
251 ret = krb5_verify_checksum (context, crypto,
252 KRB5_KU_USAGE_SIGN,
253 tmp, message_buffer->length + 8,
254 &csum);
255 free (tmp);
256 if (ret) {
257 krb5_crypto_destroy (context, crypto);
258 *minor_status = ret;
259 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
260 return GSS_S_BAD_MIC;
262 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
264 krb5_crypto_destroy (context, crypto);
265 return GSS_S_COMPLETE;
268 OM_uint32
269 _gsskrb5_verify_mic_internal
270 (OM_uint32 * minor_status,
271 const gsskrb5_ctx ctx,
272 krb5_context context,
273 const gss_buffer_t message_buffer,
274 const gss_buffer_t token_buffer,
275 gss_qop_t * qop_state,
276 char * type
279 krb5_keyblock *key;
280 OM_uint32 ret;
281 krb5_keytype keytype;
283 if (ctx->more_flags & IS_CFX)
284 return _gssapi_verify_mic_cfx (minor_status, ctx,
285 context, message_buffer, token_buffer,
286 qop_state);
288 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
289 ret = _gsskrb5i_get_token_key(ctx, context, &key);
290 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
291 if (ret) {
292 *minor_status = ret;
293 return GSS_S_FAILURE;
295 *minor_status = 0;
296 krb5_enctype_to_keytype (context, key->keytype, &keytype);
297 switch (keytype) {
298 case KEYTYPE_DES :
299 ret = verify_mic_des (minor_status, ctx, context,
300 message_buffer, token_buffer, qop_state, key,
301 type);
302 break;
303 case KEYTYPE_DES3 :
304 ret = verify_mic_des3 (minor_status, ctx, context,
305 message_buffer, token_buffer, qop_state, key,
306 type);
307 break;
308 case KEYTYPE_ARCFOUR :
309 case KEYTYPE_ARCFOUR_56 :
310 ret = _gssapi_verify_mic_arcfour (minor_status, ctx,
311 context,
312 message_buffer, token_buffer,
313 qop_state, key, type);
314 break;
315 default :
316 abort();
318 krb5_free_keyblock (context, key);
320 return ret;
323 OM_uint32
324 _gsskrb5_verify_mic
325 (OM_uint32 * minor_status,
326 const gss_ctx_id_t context_handle,
327 const gss_buffer_t message_buffer,
328 const gss_buffer_t token_buffer,
329 gss_qop_t * qop_state
332 krb5_context context;
333 OM_uint32 ret;
335 GSSAPI_KRB5_INIT (&context);
337 if (qop_state != NULL)
338 *qop_state = GSS_C_QOP_DEFAULT;
340 ret = _gsskrb5_verify_mic_internal(minor_status,
341 (gsskrb5_ctx)context_handle,
342 context,
343 message_buffer, token_buffer,
344 qop_state, "\x01\x01");
346 return ret;