1/*
2 * Copyright (C) 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* $Id: spnego_asn1.c,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
18
19/*! \file
20 * \brief Method routines generated from SPNEGO ASN.1 module.
21 * See spnego_asn1.pl for details.  Do not edit.
22 */
23
24/* Generated from spnego.asn1 */
25/* Do not edit */
26
27#ifndef __asn1_h__
28#define __asn1_h__
29
30
31#ifndef __asn1_common_definitions__
32#define __asn1_common_definitions__
33
34typedef struct octet_string {
35	size_t length;
36	void *data;
37} octet_string;
38
39typedef char *general_string;
40
41typedef char *utf8_string;
42
43typedef struct oid {
44	size_t length;
45	unsigned *components;
46} oid;
47
48#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \
49  do {                                                         \
50    (BL) = length_##T((S));                                    \
51    (B) = malloc((BL));                                        \
52    if((B) == NULL) {                                          \
53      (R) = ENOMEM;                                            \
54    } else {                                                   \
55      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \
56                       (S), (L));                              \
57      if((R) != 0) {                                           \
58        free((B));                                             \
59        (B) = NULL;                                            \
60      }                                                        \
61    }                                                          \
62  } while (0)
63
64#endif
65
66/*
67 * MechType ::= OBJECT IDENTIFIER
68 */
69
70typedef oid MechType;
71
72static int encode_MechType(unsigned char *, size_t, const MechType *, size_t *);
73static int decode_MechType(const unsigned char *, size_t, MechType *, size_t *);
74static void free_MechType(MechType *);
75/* unused declaration: length_MechType */
76/* unused declaration: copy_MechType */
77
78
79/*
80 * MechTypeList ::= SEQUENCE OF MechType
81 */
82
83typedef struct MechTypeList {
84	unsigned int len;
85	MechType *val;
86} MechTypeList;
87
88static int encode_MechTypeList(unsigned char *, size_t, const MechTypeList *, size_t *);
89static int decode_MechTypeList(const unsigned char *, size_t, MechTypeList *, size_t *);
90static void free_MechTypeList(MechTypeList *);
91/* unused declaration: length_MechTypeList */
92/* unused declaration: copy_MechTypeList */
93
94
95/*
96 * ContextFlags ::= BIT STRING { delegFlag(0), mutualFlag(1), replayFlag(2),
97 * sequenceFlag(3), anonFlag(4), confFlag(5), integFlag(6) }
98 */
99
100typedef struct ContextFlags {
101	unsigned int delegFlag:1;
102	unsigned int mutualFlag:1;
103	unsigned int replayFlag:1;
104	unsigned int sequenceFlag:1;
105	unsigned int anonFlag:1;
106	unsigned int confFlag:1;
107	unsigned int integFlag:1;
108} ContextFlags;
109
110
111static int encode_ContextFlags(unsigned char *, size_t, const ContextFlags *, size_t *);
112static int decode_ContextFlags(const unsigned char *, size_t, ContextFlags *, size_t *);
113static void free_ContextFlags(ContextFlags *);
114/* unused declaration: length_ContextFlags */
115/* unused declaration: copy_ContextFlags */
116/* unused declaration: ContextFlags2int */
117/* unused declaration: int2ContextFlags */
118/* unused declaration: asn1_ContextFlags_units */
119
120/*
121 * NegTokenInit ::= SEQUENCE { mechTypes[0]    MechTypeList, reqFlags[1]
122 * ContextFlags OPTIONAL, mechToken[2]    OCTET STRING OPTIONAL,
123 * mechListMIC[3]  OCTET STRING OPTIONAL }
124 */
125
126typedef struct NegTokenInit {
127	MechTypeList mechTypes;
128	ContextFlags *reqFlags;
129	octet_string *mechToken;
130	octet_string *mechListMIC;
131} NegTokenInit;
132
133static int encode_NegTokenInit(unsigned char *, size_t, const NegTokenInit *, size_t *);
134static int decode_NegTokenInit(const unsigned char *, size_t, NegTokenInit *, size_t *);
135static void free_NegTokenInit(NegTokenInit *);
136/* unused declaration: length_NegTokenInit */
137/* unused declaration: copy_NegTokenInit */
138
139
140/*
141 * NegTokenResp ::= SEQUENCE { negState[0]       ENUMERATED {
142 * accept-completed(0), accept-incomplete(1), reject(2), request-mic(3) }
143 * OPTIONAL, supportedMech[1]  MechType OPTIONAL, responseToken[2]  OCTET
144 * STRING OPTIONAL, mechListMIC[3]    OCTET STRING OPTIONAL }
145 */
146
147typedef struct NegTokenResp {
148	enum {
149		accept_completed = 0,
150		accept_incomplete = 1,
151		reject = 2,
152		request_mic = 3
153	} *negState;
154
155	MechType *supportedMech;
156	octet_string *responseToken;
157	octet_string *mechListMIC;
158} NegTokenResp;
159
160static int encode_NegTokenResp(unsigned char *, size_t, const NegTokenResp *, size_t *);
161static int decode_NegTokenResp(const unsigned char *, size_t, NegTokenResp *, size_t *);
162static void free_NegTokenResp(NegTokenResp *);
163/* unused declaration: length_NegTokenResp */
164/* unused declaration: copy_NegTokenResp */
165
166
167
168
169#endif				/* __asn1_h__ */
170/* Generated from spnego.asn1 */
171/* Do not edit */
172
173
174#define BACK if (e) return e; p -= l; len -= l; ret += l
175
176static int
177encode_MechType(unsigned char *p, size_t len, const MechType * data, size_t * size)
178{
179	size_t ret = 0;
180	size_t l;
181	int i, e;
182
183	i = 0;
184	e = encode_oid(p, len, data, &l);
185	BACK;
186	*size = ret;
187	return 0;
188}
189
190#define FORW if(e) goto fail; p += l; len -= l; ret += l
191
192static int
193decode_MechType(const unsigned char *p, size_t len, MechType * data, size_t * size)
194{
195	size_t ret = 0, reallen;
196	size_t l;
197	int e;
198
199	memset(data, 0, sizeof(*data));
200	reallen = 0;
201	e = decode_oid(p, len, data, &l);
202	FORW;
203	if (size)
204		*size = ret;
205	return 0;
206fail:
207	free_MechType(data);
208	return e;
209}
210
211static void
212free_MechType(MechType * data)
213{
214	free_oid(data);
215}
216
217/* unused function: length_MechType */
218
219
220/* unused function: copy_MechType */
221
222/* Generated from spnego.asn1 */
223/* Do not edit */
224
225
226#define BACK if (e) return e; p -= l; len -= l; ret += l
227
228static int
229encode_MechTypeList(unsigned char *p, size_t len, const MechTypeList * data, size_t * size)
230{
231	size_t ret = 0;
232	size_t l;
233	int i, e;
234
235	i = 0;
236	for (i = (data)->len - 1; i >= 0; --i) {
237		int oldret = ret;
238		ret = 0;
239		e = encode_MechType(p, len, &(data)->val[i], &l);
240		BACK;
241		ret += oldret;
242	}
243	e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
244	BACK;
245	*size = ret;
246	return 0;
247}
248
249#define FORW if(e) goto fail; p += l; len -= l; ret += l
250
251static int
252decode_MechTypeList(const unsigned char *p, size_t len, MechTypeList * data, size_t * size)
253{
254	size_t ret = 0, reallen;
255	size_t l;
256	int e;
257
258	memset(data, 0, sizeof(*data));
259	reallen = 0;
260	e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
261	FORW;
262	if (len < reallen)
263		return ASN1_OVERRUN;
264	len = reallen;
265	{
266		size_t origlen = len;
267		int oldret = ret;
268		ret = 0;
269		(data)->len = 0;
270		(data)->val = NULL;
271		while (ret < origlen) {
272			(data)->len++;
273			(data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len);
274			e = decode_MechType(p, len, &(data)->val[(data)->len - 1], &l);
275			FORW;
276			len = origlen - ret;
277		}
278		ret += oldret;
279	}
280	if (size)
281		*size = ret;
282	return 0;
283fail:
284	free_MechTypeList(data);
285	return e;
286}
287
288static void
289free_MechTypeList(MechTypeList * data)
290{
291	while ((data)->len) {
292		free_MechType(&(data)->val[(data)->len - 1]);
293		(data)->len--;
294	}
295	free((data)->val);
296	(data)->val = NULL;
297}
298
299/* unused function: length_MechTypeList */
300
301
302/* unused function: copy_MechTypeList */
303
304/* Generated from spnego.asn1 */
305/* Do not edit */
306
307
308#define BACK if (e) return e; p -= l; len -= l; ret += l
309
310static int
311encode_ContextFlags(unsigned char *p, size_t len, const ContextFlags * data, size_t * size)
312{
313	size_t ret = 0;
314	size_t l;
315	int i, e;
316
317	i = 0;
318	{
319		unsigned char c = 0;
320		*p-- = c;
321		len--;
322		ret++;
323		c = 0;
324		*p-- = c;
325		len--;
326		ret++;
327		c = 0;
328		*p-- = c;
329		len--;
330		ret++;
331		c = 0;
332		if (data->integFlag)
333			c |= 1 << 1;
334		if (data->confFlag)
335			c |= 1 << 2;
336		if (data->anonFlag)
337			c |= 1 << 3;
338		if (data->sequenceFlag)
339			c |= 1 << 4;
340		if (data->replayFlag)
341			c |= 1 << 5;
342		if (data->mutualFlag)
343			c |= 1 << 6;
344		if (data->delegFlag)
345			c |= 1 << 7;
346		*p-- = c;
347		*p-- = 0;
348		len -= 2;
349		ret += 2;
350	}
351
352	e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, PRIM, UT_BitString, &l);
353	BACK;
354	*size = ret;
355	return 0;
356}
357
358#define FORW if(e) goto fail; p += l; len -= l; ret += l
359
360static int
361decode_ContextFlags(const unsigned char *p, size_t len, ContextFlags * data, size_t * size)
362{
363	size_t ret = 0, reallen;
364	size_t l;
365	int e;
366
367	memset(data, 0, sizeof(*data));
368	reallen = 0;
369	e = der_match_tag_and_length(p, len, ASN1_C_UNIV, PRIM, UT_BitString, &reallen, &l);
370	FORW;
371	if (len < reallen)
372		return ASN1_OVERRUN;
373	p++;
374	len--;
375	reallen--;
376	ret++;
377	data->delegFlag = (*p >> 7) & 1;
378	data->mutualFlag = (*p >> 6) & 1;
379	data->replayFlag = (*p >> 5) & 1;
380	data->sequenceFlag = (*p >> 4) & 1;
381	data->anonFlag = (*p >> 3) & 1;
382	data->confFlag = (*p >> 2) & 1;
383	data->integFlag = (*p >> 1) & 1;
384	p += reallen;
385	len -= reallen;
386	ret += reallen;
387	if (size)
388		*size = ret;
389	return 0;
390fail:
391	free_ContextFlags(data);
392	return e;
393}
394
395static void
396free_ContextFlags(ContextFlags * data)
397{
398	(void)data;
399}
400
401/* unused function: length_ContextFlags */
402
403
404/* unused function: copy_ContextFlags */
405
406
407/* unused function: ContextFlags2int */
408
409
410/* unused function: int2ContextFlags */
411
412
413/* unused variable: ContextFlags_units */
414
415/* unused function: asn1_ContextFlags_units */
416
417/* Generated from spnego.asn1 */
418/* Do not edit */
419
420
421#define BACK if (e) return e; p -= l; len -= l; ret += l
422
423static int
424encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, size_t * size)
425{
426	size_t ret = 0;
427	size_t l;
428	int i, e;
429
430	i = 0;
431	if ((data)->mechListMIC) {
432		int oldret = ret;
433		ret = 0;
434		e = encode_octet_string(p, len, (data)->mechListMIC, &l);
435		BACK;
436		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
437		BACK;
438		ret += oldret;
439	}
440	if ((data)->mechToken) {
441		int oldret = ret;
442		ret = 0;
443		e = encode_octet_string(p, len, (data)->mechToken, &l);
444		BACK;
445		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
446		BACK;
447		ret += oldret;
448	}
449	if ((data)->reqFlags) {
450		int oldret = ret;
451		ret = 0;
452		e = encode_ContextFlags(p, len, (data)->reqFlags, &l);
453		BACK;
454		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
455		BACK;
456		ret += oldret;
457	} {
458		int oldret = ret;
459		ret = 0;
460		e = encode_MechTypeList(p, len, &(data)->mechTypes, &l);
461		BACK;
462		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
463		BACK;
464		ret += oldret;
465	}
466	e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
467	BACK;
468	*size = ret;
469	return 0;
470}
471
472#define FORW if(e) goto fail; p += l; len -= l; ret += l
473
474static int
475decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, size_t * size)
476{
477	size_t ret = 0, reallen;
478	size_t l;
479	int e;
480
481	memset(data, 0, sizeof(*data));
482	reallen = 0;
483	e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
484	FORW;
485	{
486		int dce_fix;
487		if ((dce_fix = fix_dce(reallen, &len)) < 0)
488			return ASN1_BAD_FORMAT;
489		{
490			size_t newlen, oldlen;
491
492			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
493			if (e)
494				return e;
495			else {
496				p += l;
497				len -= l;
498				ret += l;
499				e = der_get_length(p, len, &newlen, &l);
500				FORW;
501				{
502					int dce_fix;
503					oldlen = len;
504					if ((dce_fix = fix_dce(newlen, &len)) < 0)
505						return ASN1_BAD_FORMAT;
506					e = decode_MechTypeList(p, len, &(data)->mechTypes, &l);
507					FORW;
508					if (dce_fix) {
509						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
510						FORW;
511					} else
512						len = oldlen - newlen;
513				}
514			}
515		}
516		{
517			size_t newlen, oldlen;
518
519			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
520			if (e)
521				(data)->reqFlags = NULL;
522			else {
523				p += l;
524				len -= l;
525				ret += l;
526				e = der_get_length(p, len, &newlen, &l);
527				FORW;
528				{
529					int dce_fix;
530					oldlen = len;
531					if ((dce_fix = fix_dce(newlen, &len)) < 0)
532						return ASN1_BAD_FORMAT;
533					(data)->reqFlags = malloc(sizeof(*(data)->reqFlags));
534					if ((data)->reqFlags == NULL)
535						return ENOMEM;
536					e = decode_ContextFlags(p, len, (data)->reqFlags, &l);
537					FORW;
538					if (dce_fix) {
539						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
540						FORW;
541					} else
542						len = oldlen - newlen;
543				}
544			}
545		}
546		{
547			size_t newlen, oldlen;
548
549			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
550			if (e)
551				(data)->mechToken = NULL;
552			else {
553				p += l;
554				len -= l;
555				ret += l;
556				e = der_get_length(p, len, &newlen, &l);
557				FORW;
558				{
559					int dce_fix;
560					oldlen = len;
561					if ((dce_fix = fix_dce(newlen, &len)) < 0)
562						return ASN1_BAD_FORMAT;
563					(data)->mechToken = malloc(sizeof(*(data)->mechToken));
564					if ((data)->mechToken == NULL)
565						return ENOMEM;
566					e = decode_octet_string(p, len, (data)->mechToken, &l);
567					FORW;
568					if (dce_fix) {
569						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
570						FORW;
571					} else
572						len = oldlen - newlen;
573				}
574			}
575		}
576		{
577			size_t newlen, oldlen;
578
579			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
580			if (e)
581				(data)->mechListMIC = NULL;
582			else {
583				p += l;
584				len -= l;
585				ret += l;
586				e = der_get_length(p, len, &newlen, &l);
587				FORW;
588				{
589					int dce_fix;
590					oldlen = len;
591					if ((dce_fix = fix_dce(newlen, &len)) < 0)
592						return ASN1_BAD_FORMAT;
593					(data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
594					if ((data)->mechListMIC == NULL)
595						return ENOMEM;
596					e = decode_octet_string(p, len, (data)->mechListMIC, &l);
597					FORW;
598					if (dce_fix) {
599						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
600						FORW;
601					} else
602						len = oldlen - newlen;
603				}
604			}
605		}
606		if (dce_fix) {
607			e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
608			FORW;
609		}
610	}
611	if (size)
612		*size = ret;
613	return 0;
614fail:
615	free_NegTokenInit(data);
616	return e;
617}
618
619static void
620free_NegTokenInit(NegTokenInit * data)
621{
622	free_MechTypeList(&(data)->mechTypes);
623	if ((data)->reqFlags) {
624		free_ContextFlags((data)->reqFlags);
625		free((data)->reqFlags);
626		(data)->reqFlags = NULL;
627	}
628	if ((data)->mechToken) {
629		free_octet_string((data)->mechToken);
630		free((data)->mechToken);
631		(data)->mechToken = NULL;
632	}
633	if ((data)->mechListMIC) {
634		free_octet_string((data)->mechListMIC);
635		free((data)->mechListMIC);
636		(data)->mechListMIC = NULL;
637	}
638}
639
640/* unused function: length_NegTokenInit */
641
642
643/* unused function: copy_NegTokenInit */
644
645/* Generated from spnego.asn1 */
646/* Do not edit */
647
648
649#define BACK if (e) return e; p -= l; len -= l; ret += l
650
651static int
652encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, size_t * size)
653{
654	size_t ret = 0;
655	size_t l;
656	int i, e;
657
658	i = 0;
659	if ((data)->mechListMIC) {
660		int oldret = ret;
661		ret = 0;
662		e = encode_octet_string(p, len, (data)->mechListMIC, &l);
663		BACK;
664		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
665		BACK;
666		ret += oldret;
667	}
668	if ((data)->responseToken) {
669		int oldret = ret;
670		ret = 0;
671		e = encode_octet_string(p, len, (data)->responseToken, &l);
672		BACK;
673		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
674		BACK;
675		ret += oldret;
676	}
677	if ((data)->supportedMech) {
678		int oldret = ret;
679		ret = 0;
680		e = encode_MechType(p, len, (data)->supportedMech, &l);
681		BACK;
682		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
683		BACK;
684		ret += oldret;
685	}
686	if ((data)->negState) {
687		int oldret = ret;
688		ret = 0;
689		e = encode_enumerated(p, len, (data)->negState, &l);
690		BACK;
691		e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
692		BACK;
693		ret += oldret;
694	}
695	e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
696	BACK;
697	*size = ret;
698	return 0;
699}
700
701#define FORW if(e) goto fail; p += l; len -= l; ret += l
702
703static int
704decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, size_t * size)
705{
706	size_t ret = 0, reallen;
707	size_t l;
708	int e;
709
710	memset(data, 0, sizeof(*data));
711	reallen = 0;
712	e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
713	FORW;
714	{
715		int dce_fix;
716		if ((dce_fix = fix_dce(reallen, &len)) < 0)
717			return ASN1_BAD_FORMAT;
718		{
719			size_t newlen, oldlen;
720
721			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
722			if (e)
723				(data)->negState = NULL;
724			else {
725				p += l;
726				len -= l;
727				ret += l;
728				e = der_get_length(p, len, &newlen, &l);
729				FORW;
730				{
731					int dce_fix;
732					oldlen = len;
733					if ((dce_fix = fix_dce(newlen, &len)) < 0)
734						return ASN1_BAD_FORMAT;
735					(data)->negState = malloc(sizeof(*(data)->negState));
736					if ((data)->negState == NULL)
737						return ENOMEM;
738					e = decode_enumerated(p, len, (data)->negState, &l);
739					FORW;
740					if (dce_fix) {
741						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
742						FORW;
743					} else
744						len = oldlen - newlen;
745				}
746			}
747		}
748		{
749			size_t newlen, oldlen;
750
751			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
752			if (e)
753				(data)->supportedMech = NULL;
754			else {
755				p += l;
756				len -= l;
757				ret += l;
758				e = der_get_length(p, len, &newlen, &l);
759				FORW;
760				{
761					int dce_fix;
762					oldlen = len;
763					if ((dce_fix = fix_dce(newlen, &len)) < 0)
764						return ASN1_BAD_FORMAT;
765					(data)->supportedMech = malloc(sizeof(*(data)->supportedMech));
766					if ((data)->supportedMech == NULL)
767						return ENOMEM;
768					e = decode_MechType(p, len, (data)->supportedMech, &l);
769					FORW;
770					if (dce_fix) {
771						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
772						FORW;
773					} else
774						len = oldlen - newlen;
775				}
776			}
777		}
778		{
779			size_t newlen, oldlen;
780
781			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
782			if (e)
783				(data)->responseToken = NULL;
784			else {
785				p += l;
786				len -= l;
787				ret += l;
788				e = der_get_length(p, len, &newlen, &l);
789				FORW;
790				{
791					int dce_fix;
792					oldlen = len;
793					if ((dce_fix = fix_dce(newlen, &len)) < 0)
794						return ASN1_BAD_FORMAT;
795					(data)->responseToken = malloc(sizeof(*(data)->responseToken));
796					if ((data)->responseToken == NULL)
797						return ENOMEM;
798					e = decode_octet_string(p, len, (data)->responseToken, &l);
799					FORW;
800					if (dce_fix) {
801						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
802						FORW;
803					} else
804						len = oldlen - newlen;
805				}
806			}
807		}
808		{
809			size_t newlen, oldlen;
810
811			e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
812			if (e)
813				(data)->mechListMIC = NULL;
814			else {
815				p += l;
816				len -= l;
817				ret += l;
818				e = der_get_length(p, len, &newlen, &l);
819				FORW;
820				{
821					int dce_fix;
822					oldlen = len;
823					if ((dce_fix = fix_dce(newlen, &len)) < 0)
824						return ASN1_BAD_FORMAT;
825					(data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
826					if ((data)->mechListMIC == NULL)
827						return ENOMEM;
828					e = decode_octet_string(p, len, (data)->mechListMIC, &l);
829					FORW;
830					if (dce_fix) {
831						e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
832						FORW;
833					} else
834						len = oldlen - newlen;
835				}
836			}
837		}
838		if (dce_fix) {
839			e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
840			FORW;
841		}
842	}
843	if (size)
844		*size = ret;
845	return 0;
846fail:
847	free_NegTokenResp(data);
848	return e;
849}
850
851static void
852free_NegTokenResp(NegTokenResp * data)
853{
854	if ((data)->negState) {
855		free((data)->negState);
856		(data)->negState = NULL;
857	}
858	if ((data)->supportedMech) {
859		free_MechType((data)->supportedMech);
860		free((data)->supportedMech);
861		(data)->supportedMech = NULL;
862	}
863	if ((data)->responseToken) {
864		free_octet_string((data)->responseToken);
865		free((data)->responseToken);
866		(data)->responseToken = NULL;
867	}
868	if ((data)->mechListMIC) {
869		free_octet_string((data)->mechListMIC);
870		free((data)->mechListMIC);
871		(data)->mechListMIC = NULL;
872	}
873}
874
875/* unused function: length_NegTokenResp */
876
877
878/* unused function: copy_NegTokenResp */
879
880/* Generated from spnego.asn1 */
881/* Do not edit */
882
883
884/* CHOICE */
885/* unused variable: asn1_NegotiationToken_dummy_holder */
886