Remove building with NOCRYPTO option
[minix.git] / crypto / external / bsd / heimdal / dist / lib / gssapi / krb5 / verify_mic.c
blobdbeb4be7ddb41793a26da8103b79ed05c5d2222c
1 /* $NetBSD: verify_mic.c,v 1.2 2014/05/12 15:25:49 christos Exp $ */
3 /*
4 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "gsskrb5_locl.h"
38 #ifdef HEIM_WEAK_CRYPTO
40 static OM_uint32
41 verify_mic_des
42 (OM_uint32 * minor_status,
43 const gsskrb5_ctx context_handle,
44 krb5_context context,
45 const gss_buffer_t message_buffer,
46 const gss_buffer_t token_buffer,
47 gss_qop_t * qop_state,
48 krb5_keyblock *key,
49 const char *type
52 u_char *p;
53 EVP_MD_CTX *md5;
54 u_char hash[16], *seq;
55 DES_key_schedule schedule;
56 EVP_CIPHER_CTX des_ctx;
57 DES_cblock zero;
58 DES_cblock deskey;
59 uint32_t seq_number;
60 OM_uint32 ret;
61 int cmp;
63 p = token_buffer->value;
64 ret = _gsskrb5_verify_header (&p,
65 token_buffer->length,
66 type,
67 GSS_KRB5_MECHANISM);
68 if (ret)
69 return ret;
71 if (memcmp(p, "\x00\x00", 2) != 0)
72 return GSS_S_BAD_SIG;
73 p += 2;
74 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
75 return GSS_S_BAD_MIC;
76 p += 4;
77 p += 16;
79 /* verify checksum */
80 md5 = EVP_MD_CTX_create();
81 EVP_DigestInit_ex(md5, EVP_md5(), NULL);
82 EVP_DigestUpdate(md5, p - 24, 8);
83 EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length);
84 EVP_DigestFinal_ex(md5, hash, NULL);
85 EVP_MD_CTX_destroy(md5);
87 memset (&zero, 0, sizeof(zero));
88 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
90 DES_set_key_unchecked (&deskey, &schedule);
91 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
92 &schedule, &zero);
93 if (ct_memcmp (p - 8, hash, 8) != 0) {
94 memset (deskey, 0, sizeof(deskey));
95 memset (&schedule, 0, sizeof(schedule));
96 return GSS_S_BAD_MIC;
99 /* verify sequence number */
101 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
103 p -= 16;
105 EVP_CIPHER_CTX_init(&des_ctx);
106 EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
107 EVP_Cipher(&des_ctx, p, p, 8);
108 EVP_CIPHER_CTX_cleanup(&des_ctx);
110 memset (deskey, 0, sizeof(deskey));
111 memset (&schedule, 0, sizeof(schedule));
113 seq = p;
114 _gsskrb5_decode_om_uint32(seq, &seq_number);
116 if (context_handle->more_flags & LOCAL)
117 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
118 else
119 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
121 if (cmp != 0) {
122 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
123 return GSS_S_BAD_MIC;
126 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
127 if (ret) {
128 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
129 return ret;
132 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
134 return GSS_S_COMPLETE;
136 #endif
138 static OM_uint32
139 verify_mic_des3
140 (OM_uint32 * minor_status,
141 const gsskrb5_ctx context_handle,
142 krb5_context context,
143 const gss_buffer_t message_buffer,
144 const gss_buffer_t token_buffer,
145 gss_qop_t * qop_state,
146 krb5_keyblock *key,
147 const char *type
150 u_char *p;
151 u_char *seq;
152 uint32_t seq_number;
153 OM_uint32 ret;
154 krb5_crypto crypto;
155 krb5_data seq_data;
156 int cmp, docompat;
157 Checksum csum;
158 char *tmp;
159 char ivec[8];
161 p = token_buffer->value;
162 ret = _gsskrb5_verify_header (&p,
163 token_buffer->length,
164 type,
165 GSS_KRB5_MECHANISM);
166 if (ret)
167 return ret;
169 if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */
170 return GSS_S_BAD_SIG;
171 p += 2;
172 if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
173 return GSS_S_BAD_MIC;
174 p += 4;
176 ret = krb5_crypto_init(context, key,
177 ETYPE_DES3_CBC_NONE, &crypto);
178 if (ret){
179 *minor_status = ret;
180 return GSS_S_FAILURE;
183 /* verify sequence number */
184 docompat = 0;
185 retry:
186 if (docompat)
187 memset(ivec, 0, 8);
188 else
189 memcpy(ivec, p + 8, 8);
191 ret = krb5_decrypt_ivec (context,
192 crypto,
193 KRB5_KU_USAGE_SEQ,
194 p, 8, &seq_data, ivec);
195 if (ret) {
196 if (docompat++) {
197 krb5_crypto_destroy (context, crypto);
198 *minor_status = ret;
199 return GSS_S_FAILURE;
200 } else
201 goto retry;
204 if (seq_data.length != 8) {
205 krb5_data_free (&seq_data);
206 if (docompat++) {
207 krb5_crypto_destroy (context, crypto);
208 return GSS_S_BAD_MIC;
209 } else
210 goto retry;
213 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
215 seq = seq_data.data;
216 _gsskrb5_decode_om_uint32(seq, &seq_number);
218 if (context_handle->more_flags & LOCAL)
219 cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
220 else
221 cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
223 krb5_data_free (&seq_data);
224 if (cmp != 0) {
225 krb5_crypto_destroy (context, crypto);
226 *minor_status = 0;
227 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
228 return GSS_S_BAD_MIC;
231 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
232 if (ret) {
233 krb5_crypto_destroy (context, crypto);
234 *minor_status = 0;
235 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
236 return ret;
239 /* verify checksum */
241 tmp = malloc (message_buffer->length + 8);
242 if (tmp == NULL) {
243 krb5_crypto_destroy (context, crypto);
244 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
245 *minor_status = ENOMEM;
246 return GSS_S_FAILURE;
249 memcpy (tmp, p - 8, 8);
250 memcpy (tmp + 8, message_buffer->value, message_buffer->length);
252 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
253 csum.checksum.length = 20;
254 csum.checksum.data = p + 8;
256 krb5_crypto_destroy (context, crypto);
257 ret = krb5_crypto_init(context, key,
258 ETYPE_DES3_CBC_SHA1, &crypto);
259 if (ret) {
260 free (tmp);
261 *minor_status = ret;
262 return GSS_S_FAILURE;
265 ret = krb5_verify_checksum (context, crypto,
266 KRB5_KU_USAGE_SIGN,
267 tmp, message_buffer->length + 8,
268 &csum);
269 free (tmp);
270 if (ret) {
271 krb5_crypto_destroy (context, crypto);
272 *minor_status = ret;
273 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
274 return GSS_S_BAD_MIC;
276 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
278 krb5_crypto_destroy (context, crypto);
279 return GSS_S_COMPLETE;
282 OM_uint32
283 _gsskrb5_verify_mic_internal
284 (OM_uint32 * minor_status,
285 const gsskrb5_ctx ctx,
286 krb5_context context,
287 const gss_buffer_t message_buffer,
288 const gss_buffer_t token_buffer,
289 gss_qop_t * qop_state,
290 const char * type
293 krb5_keyblock *key;
294 OM_uint32 ret;
295 krb5_keytype keytype;
297 if (ctx->more_flags & IS_CFX)
298 return _gssapi_verify_mic_cfx (minor_status, ctx,
299 context, message_buffer, token_buffer,
300 qop_state);
302 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
303 ret = _gsskrb5i_get_token_key(ctx, context, &key);
304 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
305 if (ret) {
306 *minor_status = ret;
307 return GSS_S_FAILURE;
309 *minor_status = 0;
310 krb5_enctype_to_keytype (context, key->keytype, &keytype);
311 switch (keytype) {
312 case KEYTYPE_DES :
313 #ifdef HEIM_WEAK_CRYPTO
314 ret = verify_mic_des (minor_status, ctx, context,
315 message_buffer, token_buffer, qop_state, key,
316 type);
317 #else
318 ret = GSS_S_FAILURE;
319 #endif
320 break;
321 case KEYTYPE_DES3 :
322 ret = verify_mic_des3 (minor_status, ctx, context,
323 message_buffer, token_buffer, qop_state, key,
324 type);
325 break;
326 case KEYTYPE_ARCFOUR :
327 case KEYTYPE_ARCFOUR_56 :
328 ret = _gssapi_verify_mic_arcfour (minor_status, ctx,
329 context,
330 message_buffer, token_buffer,
331 qop_state, key, type);
332 break;
333 default :
334 abort();
336 krb5_free_keyblock (context, key);
338 return ret;
341 OM_uint32 GSSAPI_CALLCONV
342 _gsskrb5_verify_mic
343 (OM_uint32 * minor_status,
344 const gss_ctx_id_t context_handle,
345 const gss_buffer_t message_buffer,
346 const gss_buffer_t token_buffer,
347 gss_qop_t * qop_state
350 krb5_context context;
351 OM_uint32 ret;
353 GSSAPI_KRB5_INIT (&context);
355 if (qop_state != NULL)
356 *qop_state = GSS_C_QOP_DEFAULT;
358 ret = _gsskrb5_verify_mic_internal(minor_status,
359 (gsskrb5_ctx)context_handle,
360 context,
361 message_buffer, token_buffer,
362 qop_state, (void *)(intptr_t)"\x01\x01");
364 return ret;