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