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