1c19800e8SDoug Rabson /*
2ae771770SStanislav Sedov * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson * All rights reserved.
5c19800e8SDoug Rabson *
6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson * are met:
9c19800e8SDoug Rabson *
10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson *
13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson *
17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson * without specific prior written permission.
20c19800e8SDoug Rabson *
21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson * SUCH DAMAGE.
32c19800e8SDoug Rabson */
33c19800e8SDoug Rabson
34ae771770SStanislav Sedov #include "gsskrb5_locl.h"
35c19800e8SDoug Rabson
36ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO
37c19800e8SDoug Rabson
38c19800e8SDoug Rabson static OM_uint32
unwrap_des(OM_uint32 * minor_status,const gsskrb5_ctx context_handle,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state,krb5_keyblock * key)39c19800e8SDoug Rabson unwrap_des
40c19800e8SDoug Rabson (OM_uint32 * minor_status,
41c19800e8SDoug Rabson const gsskrb5_ctx context_handle,
42c19800e8SDoug Rabson const gss_buffer_t input_message_buffer,
43c19800e8SDoug Rabson gss_buffer_t output_message_buffer,
44c19800e8SDoug Rabson int * conf_state,
45c19800e8SDoug Rabson gss_qop_t * qop_state,
46c19800e8SDoug Rabson krb5_keyblock *key
47c19800e8SDoug Rabson )
48c19800e8SDoug Rabson {
49c19800e8SDoug Rabson u_char *p, *seq;
50c19800e8SDoug Rabson size_t len;
51ae771770SStanislav Sedov EVP_MD_CTX *md5;
52c19800e8SDoug Rabson u_char hash[16];
53e4456411SJohn Baldwin EVP_CIPHER_CTX *des_ctx;
54c19800e8SDoug Rabson DES_key_schedule schedule;
55c19800e8SDoug Rabson DES_cblock deskey;
56c19800e8SDoug Rabson DES_cblock zero;
57ae771770SStanislav Sedov size_t i;
58c19800e8SDoug Rabson uint32_t seq_number;
59c19800e8SDoug Rabson size_t padlength;
60c19800e8SDoug Rabson OM_uint32 ret;
61c19800e8SDoug Rabson int cstate;
62c19800e8SDoug Rabson int cmp;
63ae771770SStanislav Sedov int token_len;
64ae771770SStanislav Sedov
65ae771770SStanislav Sedov if (IS_DCE_STYLE(context_handle)) {
66ae771770SStanislav Sedov token_len = 22 + 8 + 15; /* 45 */
67*ed549cb0SCy Schubert if (input_message_buffer->length < token_len)
68*ed549cb0SCy Schubert return GSS_S_BAD_MECH;
69ae771770SStanislav Sedov } else {
70ae771770SStanislav Sedov token_len = input_message_buffer->length;
71ae771770SStanislav Sedov }
72c19800e8SDoug Rabson
73c19800e8SDoug Rabson p = input_message_buffer->value;
74c19800e8SDoug Rabson ret = _gsskrb5_verify_header (&p,
75ae771770SStanislav Sedov token_len,
76c19800e8SDoug Rabson "\x02\x01",
77c19800e8SDoug Rabson GSS_KRB5_MECHANISM);
78c19800e8SDoug Rabson if (ret)
79c19800e8SDoug Rabson return ret;
80c19800e8SDoug Rabson
81*ed549cb0SCy Schubert len = (p - (u_char *)input_message_buffer->value)
82*ed549cb0SCy Schubert + 22 + 8;
83*ed549cb0SCy Schubert if (input_message_buffer->length < len)
84*ed549cb0SCy Schubert return GSS_S_BAD_MECH;
85*ed549cb0SCy Schubert
86c19800e8SDoug Rabson if (memcmp (p, "\x00\x00", 2) != 0)
87c19800e8SDoug Rabson return GSS_S_BAD_SIG;
88c19800e8SDoug Rabson p += 2;
89c19800e8SDoug Rabson if (memcmp (p, "\x00\x00", 2) == 0) {
90c19800e8SDoug Rabson cstate = 1;
91c19800e8SDoug Rabson } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
92c19800e8SDoug Rabson cstate = 0;
93c19800e8SDoug Rabson } else
94c19800e8SDoug Rabson return GSS_S_BAD_MIC;
95c19800e8SDoug Rabson p += 2;
96c19800e8SDoug Rabson if(conf_state != NULL)
97c19800e8SDoug Rabson *conf_state = cstate;
98c19800e8SDoug Rabson if (memcmp (p, "\xff\xff", 2) != 0)
99c19800e8SDoug Rabson return GSS_S_DEFECTIVE_TOKEN;
100c19800e8SDoug Rabson p += 2;
101c19800e8SDoug Rabson p += 16;
102c19800e8SDoug Rabson
103c19800e8SDoug Rabson len = p - (u_char *)input_message_buffer->value;
104c19800e8SDoug Rabson
105c19800e8SDoug Rabson if(cstate) {
106c19800e8SDoug Rabson /* decrypt data */
107c19800e8SDoug Rabson memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
108ae771770SStanislav Sedov memset (&zero, 0, sizeof(zero));
109c19800e8SDoug Rabson
110c19800e8SDoug Rabson for (i = 0; i < sizeof(deskey); ++i)
111c19800e8SDoug Rabson deskey[i] ^= 0xf0;
112c19800e8SDoug Rabson
113ae771770SStanislav Sedov
114e4456411SJohn Baldwin des_ctx = EVP_CIPHER_CTX_new();
115e4456411SJohn Baldwin if (des_ctx == NULL) {
116e4456411SJohn Baldwin memset (deskey, 0, sizeof(deskey));
117e4456411SJohn Baldwin *minor_status = ENOMEM;
118e4456411SJohn Baldwin return GSS_S_FAILURE;
119e4456411SJohn Baldwin }
120e4456411SJohn Baldwin EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0);
121e4456411SJohn Baldwin EVP_Cipher(des_ctx, p, p, input_message_buffer->length - len);
122e4456411SJohn Baldwin EVP_CIPHER_CTX_free(des_ctx);
123ae771770SStanislav Sedov
124e4456411SJohn Baldwin memset (deskey, 0, sizeof(deskey));
125c19800e8SDoug Rabson }
126ae771770SStanislav Sedov
127ae771770SStanislav Sedov if (IS_DCE_STYLE(context_handle)) {
128ae771770SStanislav Sedov padlength = 0;
129ae771770SStanislav Sedov } else {
130c19800e8SDoug Rabson /* check pad */
131c19800e8SDoug Rabson ret = _gssapi_verify_pad(input_message_buffer,
132*ed549cb0SCy Schubert input_message_buffer->length - len - 8,
133c19800e8SDoug Rabson &padlength);
134c19800e8SDoug Rabson if (ret)
135c19800e8SDoug Rabson return ret;
136ae771770SStanislav Sedov }
137c19800e8SDoug Rabson
138ae771770SStanislav Sedov md5 = EVP_MD_CTX_create();
139ae771770SStanislav Sedov EVP_DigestInit_ex(md5, EVP_md5(), NULL);
140ae771770SStanislav Sedov EVP_DigestUpdate(md5, p - 24, 8);
141ae771770SStanislav Sedov EVP_DigestUpdate(md5, p, input_message_buffer->length - len);
142ae771770SStanislav Sedov EVP_DigestFinal_ex(md5, hash, NULL);
143ae771770SStanislav Sedov EVP_MD_CTX_destroy(md5);
144c19800e8SDoug Rabson
145c19800e8SDoug Rabson memset (&zero, 0, sizeof(zero));
146c19800e8SDoug Rabson memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
147ae771770SStanislav Sedov DES_set_key_unchecked (&deskey, &schedule);
148c19800e8SDoug Rabson DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
149c19800e8SDoug Rabson &schedule, &zero);
150e4456411SJohn Baldwin if (ct_memcmp (p - 8, hash, 8) != 0) {
151e4456411SJohn Baldwin memset (deskey, 0, sizeof(deskey));
152e4456411SJohn Baldwin memset (&schedule, 0, sizeof(schedule));
153c19800e8SDoug Rabson return GSS_S_BAD_MIC;
154e4456411SJohn Baldwin }
155c19800e8SDoug Rabson
156c19800e8SDoug Rabson /* verify sequence number */
157c19800e8SDoug Rabson
158e4456411SJohn Baldwin des_ctx = EVP_CIPHER_CTX_new();
159e4456411SJohn Baldwin if (des_ctx == NULL) {
160e4456411SJohn Baldwin memset (deskey, 0, sizeof(deskey));
161e4456411SJohn Baldwin memset (&schedule, 0, sizeof(schedule));
162e4456411SJohn Baldwin *minor_status = ENOMEM;
163e4456411SJohn Baldwin return GSS_S_FAILURE;
164e4456411SJohn Baldwin }
165e4456411SJohn Baldwin
166c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
167c19800e8SDoug Rabson
168c19800e8SDoug Rabson p -= 16;
169ae771770SStanislav Sedov
170e4456411SJohn Baldwin EVP_CipherInit_ex(des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0);
171e4456411SJohn Baldwin EVP_Cipher(des_ctx, p, p, 8);
172e4456411SJohn Baldwin EVP_CIPHER_CTX_free(des_ctx);
173c19800e8SDoug Rabson
174c19800e8SDoug Rabson memset (deskey, 0, sizeof(deskey));
175c19800e8SDoug Rabson memset (&schedule, 0, sizeof(schedule));
176c19800e8SDoug Rabson
177c19800e8SDoug Rabson seq = p;
178c19800e8SDoug Rabson _gsskrb5_decode_om_uint32(seq, &seq_number);
179c19800e8SDoug Rabson
180c19800e8SDoug Rabson if (context_handle->more_flags & LOCAL)
181ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
182c19800e8SDoug Rabson else
183ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
184c19800e8SDoug Rabson
185c19800e8SDoug Rabson if (cmp != 0) {
186c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
187c19800e8SDoug Rabson return GSS_S_BAD_MIC;
188c19800e8SDoug Rabson }
189c19800e8SDoug Rabson
190c19800e8SDoug Rabson ret = _gssapi_msg_order_check(context_handle->order, seq_number);
191c19800e8SDoug Rabson if (ret) {
192c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
193c19800e8SDoug Rabson return ret;
194c19800e8SDoug Rabson }
195c19800e8SDoug Rabson
196c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
197c19800e8SDoug Rabson
198c19800e8SDoug Rabson /* copy out data */
199c19800e8SDoug Rabson
200c19800e8SDoug Rabson output_message_buffer->length = input_message_buffer->length
201c19800e8SDoug Rabson - len - padlength - 8;
202c19800e8SDoug Rabson output_message_buffer->value = malloc(output_message_buffer->length);
203c19800e8SDoug Rabson if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
204c19800e8SDoug Rabson return GSS_S_FAILURE;
205*ed549cb0SCy Schubert if (output_message_buffer->value != NULL)
206c19800e8SDoug Rabson memcpy (output_message_buffer->value,
207c19800e8SDoug Rabson p + 24,
208c19800e8SDoug Rabson output_message_buffer->length);
209c19800e8SDoug Rabson return GSS_S_COMPLETE;
210c19800e8SDoug Rabson }
211ae771770SStanislav Sedov #endif
212c19800e8SDoug Rabson
213c19800e8SDoug Rabson static OM_uint32
unwrap_des3(OM_uint32 * minor_status,const gsskrb5_ctx context_handle,krb5_context context,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state,krb5_keyblock * key)214c19800e8SDoug Rabson unwrap_des3
215c19800e8SDoug Rabson (OM_uint32 * minor_status,
216c19800e8SDoug Rabson const gsskrb5_ctx context_handle,
217c19800e8SDoug Rabson krb5_context context,
218c19800e8SDoug Rabson const gss_buffer_t input_message_buffer,
219c19800e8SDoug Rabson gss_buffer_t output_message_buffer,
220c19800e8SDoug Rabson int * conf_state,
221c19800e8SDoug Rabson gss_qop_t * qop_state,
222c19800e8SDoug Rabson krb5_keyblock *key
223c19800e8SDoug Rabson )
224c19800e8SDoug Rabson {
225c19800e8SDoug Rabson u_char *p;
226c19800e8SDoug Rabson size_t len;
227c19800e8SDoug Rabson u_char *seq;
228c19800e8SDoug Rabson krb5_data seq_data;
229c19800e8SDoug Rabson u_char cksum[20];
230c19800e8SDoug Rabson uint32_t seq_number;
231c19800e8SDoug Rabson size_t padlength;
232c19800e8SDoug Rabson OM_uint32 ret;
233c19800e8SDoug Rabson int cstate;
234c19800e8SDoug Rabson krb5_crypto crypto;
235c19800e8SDoug Rabson Checksum csum;
236c19800e8SDoug Rabson int cmp;
237ae771770SStanislav Sedov int token_len;
238ae771770SStanislav Sedov
239ae771770SStanislav Sedov if (IS_DCE_STYLE(context_handle)) {
240ae771770SStanislav Sedov token_len = 34 + 8 + 15; /* 57 */
241*ed549cb0SCy Schubert if (input_message_buffer->length < token_len)
242*ed549cb0SCy Schubert return GSS_S_BAD_MECH;
243ae771770SStanislav Sedov } else {
244ae771770SStanislav Sedov token_len = input_message_buffer->length;
245ae771770SStanislav Sedov }
246c19800e8SDoug Rabson
247c19800e8SDoug Rabson p = input_message_buffer->value;
248c19800e8SDoug Rabson ret = _gsskrb5_verify_header (&p,
249ae771770SStanislav Sedov token_len,
250c19800e8SDoug Rabson "\x02\x01",
251c19800e8SDoug Rabson GSS_KRB5_MECHANISM);
252c19800e8SDoug Rabson if (ret)
253c19800e8SDoug Rabson return ret;
254c19800e8SDoug Rabson
255*ed549cb0SCy Schubert len = (p - (u_char *)input_message_buffer->value)
256*ed549cb0SCy Schubert + 34 + 8;
257*ed549cb0SCy Schubert if (input_message_buffer->length < len)
258*ed549cb0SCy Schubert return GSS_S_BAD_MECH;
259*ed549cb0SCy Schubert
260*ed549cb0SCy Schubert if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
261c19800e8SDoug Rabson return GSS_S_BAD_SIG;
262c19800e8SDoug Rabson p += 2;
263ae771770SStanislav Sedov if (ct_memcmp (p, "\x02\x00", 2) == 0) {
264c19800e8SDoug Rabson cstate = 1;
265ae771770SStanislav Sedov } else if (ct_memcmp (p, "\xff\xff", 2) == 0) {
266c19800e8SDoug Rabson cstate = 0;
267c19800e8SDoug Rabson } else
268c19800e8SDoug Rabson return GSS_S_BAD_MIC;
269c19800e8SDoug Rabson p += 2;
270c19800e8SDoug Rabson if(conf_state != NULL)
271c19800e8SDoug Rabson *conf_state = cstate;
272ae771770SStanislav Sedov if (ct_memcmp (p, "\xff\xff", 2) != 0)
273c19800e8SDoug Rabson return GSS_S_DEFECTIVE_TOKEN;
274c19800e8SDoug Rabson p += 2;
275c19800e8SDoug Rabson p += 28;
276c19800e8SDoug Rabson
277c19800e8SDoug Rabson len = p - (u_char *)input_message_buffer->value;
278c19800e8SDoug Rabson
279c19800e8SDoug Rabson if(cstate) {
280c19800e8SDoug Rabson /* decrypt data */
281c19800e8SDoug Rabson krb5_data tmp;
282c19800e8SDoug Rabson
283c19800e8SDoug Rabson ret = krb5_crypto_init(context, key,
284c19800e8SDoug Rabson ETYPE_DES3_CBC_NONE, &crypto);
285c19800e8SDoug Rabson if (ret) {
286c19800e8SDoug Rabson *minor_status = ret;
287c19800e8SDoug Rabson return GSS_S_FAILURE;
288c19800e8SDoug Rabson }
289c19800e8SDoug Rabson ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
290c19800e8SDoug Rabson p, input_message_buffer->length - len, &tmp);
291c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto);
292c19800e8SDoug Rabson if (ret) {
293c19800e8SDoug Rabson *minor_status = ret;
294c19800e8SDoug Rabson return GSS_S_FAILURE;
295c19800e8SDoug Rabson }
296c19800e8SDoug Rabson assert (tmp.length == input_message_buffer->length - len);
297c19800e8SDoug Rabson
298c19800e8SDoug Rabson memcpy (p, tmp.data, tmp.length);
299c19800e8SDoug Rabson krb5_data_free(&tmp);
300c19800e8SDoug Rabson }
301ae771770SStanislav Sedov
302ae771770SStanislav Sedov if (IS_DCE_STYLE(context_handle)) {
303ae771770SStanislav Sedov padlength = 0;
304ae771770SStanislav Sedov } else {
305c19800e8SDoug Rabson /* check pad */
306c19800e8SDoug Rabson ret = _gssapi_verify_pad(input_message_buffer,
307*ed549cb0SCy Schubert input_message_buffer->length - len - 8,
308c19800e8SDoug Rabson &padlength);
309c19800e8SDoug Rabson if (ret)
310c19800e8SDoug Rabson return ret;
311ae771770SStanislav Sedov }
312c19800e8SDoug Rabson
313c19800e8SDoug Rabson /* verify sequence number */
314c19800e8SDoug Rabson
315c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
316c19800e8SDoug Rabson
317c19800e8SDoug Rabson p -= 28;
318c19800e8SDoug Rabson
319c19800e8SDoug Rabson ret = krb5_crypto_init(context, key,
320c19800e8SDoug Rabson ETYPE_DES3_CBC_NONE, &crypto);
321c19800e8SDoug Rabson if (ret) {
322c19800e8SDoug Rabson *minor_status = ret;
323c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
324c19800e8SDoug Rabson return GSS_S_FAILURE;
325c19800e8SDoug Rabson }
326c19800e8SDoug Rabson {
327c19800e8SDoug Rabson DES_cblock ivec;
328c19800e8SDoug Rabson
329c19800e8SDoug Rabson memcpy(&ivec, p + 8, 8);
330c19800e8SDoug Rabson ret = krb5_decrypt_ivec (context,
331c19800e8SDoug Rabson crypto,
332c19800e8SDoug Rabson KRB5_KU_USAGE_SEQ,
333c19800e8SDoug Rabson p, 8, &seq_data,
334c19800e8SDoug Rabson &ivec);
335c19800e8SDoug Rabson }
336c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto);
337c19800e8SDoug Rabson if (ret) {
338c19800e8SDoug Rabson *minor_status = ret;
339c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
340c19800e8SDoug Rabson return GSS_S_FAILURE;
341c19800e8SDoug Rabson }
342c19800e8SDoug Rabson if (seq_data.length != 8) {
343c19800e8SDoug Rabson krb5_data_free (&seq_data);
344c19800e8SDoug Rabson *minor_status = 0;
345c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
346c19800e8SDoug Rabson return GSS_S_BAD_MIC;
347c19800e8SDoug Rabson }
348c19800e8SDoug Rabson
349c19800e8SDoug Rabson seq = seq_data.data;
350c19800e8SDoug Rabson _gsskrb5_decode_om_uint32(seq, &seq_number);
351c19800e8SDoug Rabson
352c19800e8SDoug Rabson if (context_handle->more_flags & LOCAL)
353ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
354c19800e8SDoug Rabson else
355ae771770SStanislav Sedov cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4);
356c19800e8SDoug Rabson
357c19800e8SDoug Rabson krb5_data_free (&seq_data);
358c19800e8SDoug Rabson if (cmp != 0) {
359c19800e8SDoug Rabson *minor_status = 0;
360c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
361c19800e8SDoug Rabson return GSS_S_BAD_MIC;
362c19800e8SDoug Rabson }
363c19800e8SDoug Rabson
364c19800e8SDoug Rabson ret = _gssapi_msg_order_check(context_handle->order, seq_number);
365c19800e8SDoug Rabson if (ret) {
366c19800e8SDoug Rabson *minor_status = 0;
367c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
368c19800e8SDoug Rabson return ret;
369c19800e8SDoug Rabson }
370c19800e8SDoug Rabson
371c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
372c19800e8SDoug Rabson
373c19800e8SDoug Rabson /* verify checksum */
374c19800e8SDoug Rabson
375c19800e8SDoug Rabson memcpy (cksum, p + 8, 20);
376c19800e8SDoug Rabson
377c19800e8SDoug Rabson memcpy (p + 20, p - 8, 8);
378c19800e8SDoug Rabson
379c19800e8SDoug Rabson csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
380c19800e8SDoug Rabson csum.checksum.length = 20;
381c19800e8SDoug Rabson csum.checksum.data = cksum;
382c19800e8SDoug Rabson
383c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 0, &crypto);
384c19800e8SDoug Rabson if (ret) {
385c19800e8SDoug Rabson *minor_status = ret;
386c19800e8SDoug Rabson return GSS_S_FAILURE;
387c19800e8SDoug Rabson }
388c19800e8SDoug Rabson
389c19800e8SDoug Rabson ret = krb5_verify_checksum (context, crypto,
390c19800e8SDoug Rabson KRB5_KU_USAGE_SIGN,
391c19800e8SDoug Rabson p + 20,
392c19800e8SDoug Rabson input_message_buffer->length - len + 8,
393c19800e8SDoug Rabson &csum);
394c19800e8SDoug Rabson krb5_crypto_destroy (context, crypto);
395c19800e8SDoug Rabson if (ret) {
396c19800e8SDoug Rabson *minor_status = ret;
397c19800e8SDoug Rabson return GSS_S_FAILURE;
398c19800e8SDoug Rabson }
399c19800e8SDoug Rabson
400c19800e8SDoug Rabson /* copy out data */
401c19800e8SDoug Rabson
402c19800e8SDoug Rabson output_message_buffer->length = input_message_buffer->length
403c19800e8SDoug Rabson - len - padlength - 8;
404c19800e8SDoug Rabson output_message_buffer->value = malloc(output_message_buffer->length);
405c19800e8SDoug Rabson if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
406c19800e8SDoug Rabson return GSS_S_FAILURE;
407*ed549cb0SCy Schubert if (output_message_buffer->value != NULL)
408c19800e8SDoug Rabson memcpy (output_message_buffer->value,
409c19800e8SDoug Rabson p + 36,
410c19800e8SDoug Rabson output_message_buffer->length);
411c19800e8SDoug Rabson return GSS_S_COMPLETE;
412c19800e8SDoug Rabson }
413c19800e8SDoug Rabson
_gsskrb5_unwrap(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,const gss_buffer_t input_message_buffer,gss_buffer_t output_message_buffer,int * conf_state,gss_qop_t * qop_state)414ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap
415c19800e8SDoug Rabson (OM_uint32 * minor_status,
416c19800e8SDoug Rabson const gss_ctx_id_t context_handle,
417c19800e8SDoug Rabson const gss_buffer_t input_message_buffer,
418c19800e8SDoug Rabson gss_buffer_t output_message_buffer,
419c19800e8SDoug Rabson int * conf_state,
420c19800e8SDoug Rabson gss_qop_t * qop_state
421c19800e8SDoug Rabson )
422c19800e8SDoug Rabson {
423c19800e8SDoug Rabson krb5_keyblock *key;
424c19800e8SDoug Rabson krb5_context context;
425c19800e8SDoug Rabson OM_uint32 ret;
426c19800e8SDoug Rabson krb5_keytype keytype;
427c19800e8SDoug Rabson gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
428c19800e8SDoug Rabson
429c19800e8SDoug Rabson output_message_buffer->value = NULL;
430c19800e8SDoug Rabson output_message_buffer->length = 0;
431ae771770SStanislav Sedov if (qop_state != NULL)
432ae771770SStanislav Sedov *qop_state = GSS_C_QOP_DEFAULT;
433c19800e8SDoug Rabson
434c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context);
435c19800e8SDoug Rabson
436ae771770SStanislav Sedov if (ctx->more_flags & IS_CFX)
437ae771770SStanislav Sedov return _gssapi_unwrap_cfx (minor_status, ctx, context,
438ae771770SStanislav Sedov input_message_buffer, output_message_buffer,
439ae771770SStanislav Sedov conf_state, qop_state);
440ae771770SStanislav Sedov
441c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
442c19800e8SDoug Rabson ret = _gsskrb5i_get_token_key(ctx, context, &key);
443c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
444c19800e8SDoug Rabson if (ret) {
445c19800e8SDoug Rabson *minor_status = ret;
446c19800e8SDoug Rabson return GSS_S_FAILURE;
447c19800e8SDoug Rabson }
448c19800e8SDoug Rabson krb5_enctype_to_keytype (context, key->keytype, &keytype);
449c19800e8SDoug Rabson
450c19800e8SDoug Rabson *minor_status = 0;
451c19800e8SDoug Rabson
452c19800e8SDoug Rabson switch (keytype) {
453c19800e8SDoug Rabson case KEYTYPE_DES :
454ae771770SStanislav Sedov #ifdef HEIM_WEAK_CRYPTO
455c19800e8SDoug Rabson ret = unwrap_des (minor_status, ctx,
456c19800e8SDoug Rabson input_message_buffer, output_message_buffer,
457c19800e8SDoug Rabson conf_state, qop_state, key);
458ae771770SStanislav Sedov #else
459ae771770SStanislav Sedov ret = GSS_S_FAILURE;
460ae771770SStanislav Sedov #endif
461c19800e8SDoug Rabson break;
462c19800e8SDoug Rabson case KEYTYPE_DES3 :
463c19800e8SDoug Rabson ret = unwrap_des3 (minor_status, ctx, context,
464c19800e8SDoug Rabson input_message_buffer, output_message_buffer,
465c19800e8SDoug Rabson conf_state, qop_state, key);
466c19800e8SDoug Rabson break;
467c19800e8SDoug Rabson case KEYTYPE_ARCFOUR:
468c19800e8SDoug Rabson case KEYTYPE_ARCFOUR_56:
469c19800e8SDoug Rabson ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
470c19800e8SDoug Rabson input_message_buffer, output_message_buffer,
471c19800e8SDoug Rabson conf_state, qop_state, key);
472c19800e8SDoug Rabson break;
473c19800e8SDoug Rabson default :
474ae771770SStanislav Sedov abort();
475c19800e8SDoug Rabson break;
476c19800e8SDoug Rabson }
477c19800e8SDoug Rabson krb5_free_keyblock (context, key);
478c19800e8SDoug Rabson return ret;
479c19800e8SDoug Rabson }
480