1*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*7c478bd9Sstevel@tonic-gate /*
3*7c478bd9Sstevel@tonic-gate  * src/lib/krb5/asn.1/asn1_k_decode.c
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * Copyright 1994 by the Massachusetts Institute of Technology.
6*7c478bd9Sstevel@tonic-gate  * All Rights Reserved.
7*7c478bd9Sstevel@tonic-gate  *
8*7c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
9*7c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
10*7c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
11*7c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
12*7c478bd9Sstevel@tonic-gate  *
13*7c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14*7c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
15*7c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
16*7c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
17*7c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
18*7c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
19*7c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
20*7c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
21*7c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
22*7c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
23*7c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
24*7c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
25*7c478bd9Sstevel@tonic-gate  * or implied warranty.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include "asn1_k_decode.h"
29*7c478bd9Sstevel@tonic-gate #include "asn1_decode.h"
30*7c478bd9Sstevel@tonic-gate #include "asn1_get.h"
31*7c478bd9Sstevel@tonic-gate #include "asn1_misc.h"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /* Declare useful decoder variables. */
34*7c478bd9Sstevel@tonic-gate #define setup()					\
35*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;			\
36*7c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
37*7c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
38*7c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
39*7c478bd9Sstevel@tonic-gate   unsigned int length, taglen
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #define unused_var(x) if (0) { x = 0; x = x - x; }
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /* This is used for prefetch of next tag in sequence. */
44*7c478bd9Sstevel@tonic-gate #define next_tag()								\
45*7c478bd9Sstevel@tonic-gate { taginfo t2;									\
46*7c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(&subbuf, &t2);					\
47*7c478bd9Sstevel@tonic-gate   if (retval) return retval;							\
48*7c478bd9Sstevel@tonic-gate   /* Copy out to match previous functionality, until better integrated.  */	\
49*7c478bd9Sstevel@tonic-gate   asn1class = t2.asn1class;							\
50*7c478bd9Sstevel@tonic-gate   construction = t2.construction;						\
51*7c478bd9Sstevel@tonic-gate   tagnum = t2.tagnum;								\
52*7c478bd9Sstevel@tonic-gate   taglen = t2.length;								\
53*7c478bd9Sstevel@tonic-gate   indef = t2.indef;								\
54*7c478bd9Sstevel@tonic-gate }
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /* Force check for EOC tag. */
57*7c478bd9Sstevel@tonic-gate #define get_eoc()									\
58*7c478bd9Sstevel@tonic-gate     {											\
59*7c478bd9Sstevel@tonic-gate 	taginfo t3;									\
60*7c478bd9Sstevel@tonic-gate 	retval = asn1_get_tag_2(&subbuf, &t3);						\
61*7c478bd9Sstevel@tonic-gate 	if(retval) return retval;							\
62*7c478bd9Sstevel@tonic-gate         if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)				\
63*7c478bd9Sstevel@tonic-gate 	    return ASN1_MISSING_EOC;							\
64*7c478bd9Sstevel@tonic-gate         /* Copy out to match previous functionality, until better integrated.  */	\
65*7c478bd9Sstevel@tonic-gate 	asn1class = t3.asn1class;							\
66*7c478bd9Sstevel@tonic-gate 	construction = t3.construction;							\
67*7c478bd9Sstevel@tonic-gate 	tagnum = t3.tagnum;								\
68*7c478bd9Sstevel@tonic-gate 	taglen = t3.length;								\
69*7c478bd9Sstevel@tonic-gate 	indef = t3.indef;								\
70*7c478bd9Sstevel@tonic-gate     }
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define alloc_field(var, type)			\
73*7c478bd9Sstevel@tonic-gate   var = (type*)calloc(1, sizeof(type));		\
74*7c478bd9Sstevel@tonic-gate   if ((var) == NULL) return ENOMEM
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate #define free_field(var)			\
77*7c478bd9Sstevel@tonic-gate   if ((var) != NULL) { free(var); var = NULL; }
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /* Fetch an expected APPLICATION class tag and verify. */
80*7c478bd9Sstevel@tonic-gate #define apptag(tagexpect)								\
81*7c478bd9Sstevel@tonic-gate   {											\
82*7c478bd9Sstevel@tonic-gate       taginfo t1;									\
83*7c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t1);						\
84*7c478bd9Sstevel@tonic-gate       if (retval) return retval;						   	\
85*7c478bd9Sstevel@tonic-gate       if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED ||	   	\
86*7c478bd9Sstevel@tonic-gate 	  t1.tagnum != (tagexpect)) return ASN1_BAD_ID;					\
87*7c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */		\
88*7c478bd9Sstevel@tonic-gate       asn1class = t1.asn1class;								\
89*7c478bd9Sstevel@tonic-gate       construction = t1.construction;							\
90*7c478bd9Sstevel@tonic-gate       tagnum = t1.tagnum;								\
91*7c478bd9Sstevel@tonic-gate       applen = t1.length;								\
92*7c478bd9Sstevel@tonic-gate   }
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /**** normal fields ****/
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate /*
97*7c478bd9Sstevel@tonic-gate  * get_field_body
98*7c478bd9Sstevel@tonic-gate  *
99*7c478bd9Sstevel@tonic-gate  * Get bare field.  This also prefetches the next tag.  The call to
100*7c478bd9Sstevel@tonic-gate  * get_eoc() assumes that any values fetched by this macro are
101*7c478bd9Sstevel@tonic-gate  * enclosed in a context-specific tag.
102*7c478bd9Sstevel@tonic-gate  */
103*7c478bd9Sstevel@tonic-gate #define get_field_body(var, decoder)		\
104*7c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(var));		\
105*7c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
106*7c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
107*7c478bd9Sstevel@tonic-gate   next_tag()
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate /*
110*7c478bd9Sstevel@tonic-gate  * get_field
111*7c478bd9Sstevel@tonic-gate  *
112*7c478bd9Sstevel@tonic-gate  * Get field having an expected context specific tag.  This assumes
113*7c478bd9Sstevel@tonic-gate  * that context-specific tags are monotonically increasing in its
114*7c478bd9Sstevel@tonic-gate  * verification of tag numbers.
115*7c478bd9Sstevel@tonic-gate  */
116*7c478bd9Sstevel@tonic-gate #define get_field(var, tagexpect, decoder)				\
117*7c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
118*7c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
119*7c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
120*7c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
121*7c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
122*7c478bd9Sstevel@tonic-gate   get_field_body(var,decoder)
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate /*
125*7c478bd9Sstevel@tonic-gate  * opt_field
126*7c478bd9Sstevel@tonic-gate  *
127*7c478bd9Sstevel@tonic-gate  * Get an optional field with an expected context specific tag.
128*7c478bd9Sstevel@tonic-gate  * Assumes that OPTVAL will have the default value, thus failing to
129*7c478bd9Sstevel@tonic-gate  * distinguish between absent optional values and present optional
130*7c478bd9Sstevel@tonic-gate  * values that happen to have the value of OPTVAL.
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate #define opt_field(var, tagexpect, decoder, optvalue)			\
133*7c478bd9Sstevel@tonic-gate   if (asn1buf_remains(&subbuf, seqindef)) {				\
134*7c478bd9Sstevel@tonic-gate     if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
135*7c478bd9Sstevel@tonic-gate 	&& (tagnum || taglen || asn1class != UNIVERSAL))		\
136*7c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;						\
137*7c478bd9Sstevel@tonic-gate     if (tagnum == (tagexpect)) {					\
138*7c478bd9Sstevel@tonic-gate       get_field_body(var, decoder);					\
139*7c478bd9Sstevel@tonic-gate     } else var = optvalue;						\
140*7c478bd9Sstevel@tonic-gate   }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate /**** fields w/ length ****/
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /* similar to get_field_body */
145*7c478bd9Sstevel@tonic-gate #define get_lenfield_body(len, var, decoder)	\
146*7c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(len), &(var));	\
147*7c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
148*7c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
149*7c478bd9Sstevel@tonic-gate   next_tag()
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate /* similar to get_field_body */
152*7c478bd9Sstevel@tonic-gate #define get_lenfield(len, var, tagexpect, decoder)			\
153*7c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
154*7c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
155*7c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
156*7c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
157*7c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
158*7c478bd9Sstevel@tonic-gate   get_lenfield_body(len, var, decoder)
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate /* similar to opt_field */
161*7c478bd9Sstevel@tonic-gate #define opt_lenfield(len, var, tagexpect, decoder)	\
162*7c478bd9Sstevel@tonic-gate   if (tagnum == (tagexpect)) {				\
163*7c478bd9Sstevel@tonic-gate     get_lenfield_body(len, var, decoder);		\
164*7c478bd9Sstevel@tonic-gate   } else { len = 0; var = 0; }
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  * begin_structure
168*7c478bd9Sstevel@tonic-gate  *
169*7c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE types.  This is meant
170*7c478bd9Sstevel@tonic-gate  * to be called in an inner block that ends with a call to
171*7c478bd9Sstevel@tonic-gate  * end_structure().
172*7c478bd9Sstevel@tonic-gate  */
173*7c478bd9Sstevel@tonic-gate #define begin_structure()					\
174*7c478bd9Sstevel@tonic-gate   asn1buf subbuf;						\
175*7c478bd9Sstevel@tonic-gate   int seqindef;							\
176*7c478bd9Sstevel@tonic-gate   int indef;							\
177*7c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqindef);		\
178*7c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
179*7c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
180*7c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
181*7c478bd9Sstevel@tonic-gate   next_tag()
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate /* skip trailing garbage */
184*7c478bd9Sstevel@tonic-gate #define end_structure()						\
185*7c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum,	\
186*7c478bd9Sstevel@tonic-gate 			length, indef, seqindef);		\
187*7c478bd9Sstevel@tonic-gate   if (retval) return retval
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * sequence_of
191*7c478bd9Sstevel@tonic-gate  *
192*7c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE OF types.  This is
193*7c478bd9Sstevel@tonic-gate  * meant to be called in an inner block that ends with a call to
194*7c478bd9Sstevel@tonic-gate  * end_sequence_of().
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate #define sequence_of(buf)			\
197*7c478bd9Sstevel@tonic-gate   unsigned int length, taglen;			\
198*7c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
199*7c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
200*7c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
201*7c478bd9Sstevel@tonic-gate   int indef;					\
202*7c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate  * sequence_of_no_tagvars
206*7c478bd9Sstevel@tonic-gate  *
207*7c478bd9Sstevel@tonic-gate  * This is meant for use inside decoder functions that have an outer
208*7c478bd9Sstevel@tonic-gate  * sequence structure and thus declares variables of different names
209*7c478bd9Sstevel@tonic-gate  * than does sequence_of() to avoid shadowing.
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate #define sequence_of_no_tagvars(buf)		\
212*7c478bd9Sstevel@tonic-gate   asn1_class eseqclass;				\
213*7c478bd9Sstevel@tonic-gate   asn1_construction eseqconstr;			\
214*7c478bd9Sstevel@tonic-gate   asn1_tagnum eseqnum;				\
215*7c478bd9Sstevel@tonic-gate   unsigned int eseqlen;				\
216*7c478bd9Sstevel@tonic-gate   int eseqindef;				\
217*7c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate /*
220*7c478bd9Sstevel@tonic-gate  * sequence_of_common
221*7c478bd9Sstevel@tonic-gate  *
222*7c478bd9Sstevel@tonic-gate  * Fetches the outer SEQUENCE OF length info into {length,seqofindef}
223*7c478bd9Sstevel@tonic-gate  * and imbeds an inner buffer seqbuf.  Unlike begin_structure(), it
224*7c478bd9Sstevel@tonic-gate  * does not prefetch the next tag.
225*7c478bd9Sstevel@tonic-gate  */
226*7c478bd9Sstevel@tonic-gate #define sequence_of_common(buf)					\
227*7c478bd9Sstevel@tonic-gate   int size = 0;							\
228*7c478bd9Sstevel@tonic-gate   asn1buf seqbuf;						\
229*7c478bd9Sstevel@tonic-gate   int seqofindef;						\
230*7c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqofindef);	\
231*7c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
232*7c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef);	\
233*7c478bd9Sstevel@tonic-gate   if (retval) return retval
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate /*
236*7c478bd9Sstevel@tonic-gate  * end_sequence_of
237*7c478bd9Sstevel@tonic-gate  *
238*7c478bd9Sstevel@tonic-gate  * Attempts to fetch an EOC tag, if any, and to sync over trailing
239*7c478bd9Sstevel@tonic-gate  * garbage, if any.
240*7c478bd9Sstevel@tonic-gate  */
241*7c478bd9Sstevel@tonic-gate #define end_sequence_of(buf)							\
242*7c478bd9Sstevel@tonic-gate   {										\
243*7c478bd9Sstevel@tonic-gate       taginfo t4;								\
244*7c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t4);					\
245*7c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
246*7c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
247*7c478bd9Sstevel@tonic-gate       asn1class = t4.asn1class;							\
248*7c478bd9Sstevel@tonic-gate       construction = t4.construction;						\
249*7c478bd9Sstevel@tonic-gate       tagnum = t4.tagnum;							\
250*7c478bd9Sstevel@tonic-gate       taglen = t4.length;							\
251*7c478bd9Sstevel@tonic-gate       indef = t4.indef;								\
252*7c478bd9Sstevel@tonic-gate   }										\
253*7c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum,			\
254*7c478bd9Sstevel@tonic-gate 			length, indef, seqofindef);				\
255*7c478bd9Sstevel@tonic-gate   if (retval) return retval;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate  * end_sequence_of_no_tagvars
259*7c478bd9Sstevel@tonic-gate  *
260*7c478bd9Sstevel@tonic-gate  * Like end_sequence_of(), but uses the different (non-shadowing)
261*7c478bd9Sstevel@tonic-gate  * variable names.
262*7c478bd9Sstevel@tonic-gate  */
263*7c478bd9Sstevel@tonic-gate #define end_sequence_of_no_tagvars(buf)						\
264*7c478bd9Sstevel@tonic-gate   {										\
265*7c478bd9Sstevel@tonic-gate       taginfo t5;								\
266*7c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t5);					\
267*7c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
268*7c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
269*7c478bd9Sstevel@tonic-gate       eseqclass = t5.asn1class;							\
270*7c478bd9Sstevel@tonic-gate       eseqconstr = t5.construction;						\
271*7c478bd9Sstevel@tonic-gate       eseqnum = t5.tagnum;							\
272*7c478bd9Sstevel@tonic-gate       eseqlen = t5.length;							\
273*7c478bd9Sstevel@tonic-gate       eseqindef = t5.indef;							\
274*7c478bd9Sstevel@tonic-gate   }										\
275*7c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum,			\
276*7c478bd9Sstevel@tonic-gate 			eseqlen, eseqindef, seqofindef);			\
277*7c478bd9Sstevel@tonic-gate   if (retval) return retval;
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate #define cleanup()				\
280*7c478bd9Sstevel@tonic-gate   return 0
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate /* scalars */
283*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val)
284*7c478bd9Sstevel@tonic-gate {
285*7c478bd9Sstevel@tonic-gate     time_t	t;
286*7c478bd9Sstevel@tonic-gate     asn1_error_code retval;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate     retval =  asn1_decode_generaltime(buf,&t);
289*7c478bd9Sstevel@tonic-gate     if (retval)
290*7c478bd9Sstevel@tonic-gate 	return retval;
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate     *val = t;
293*7c478bd9Sstevel@tonic-gate     return 0;
294*7c478bd9Sstevel@tonic-gate }
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate #define integer_convert(fname,ktype)\
297*7c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
298*7c478bd9Sstevel@tonic-gate {\
299*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
300*7c478bd9Sstevel@tonic-gate   long n;\
301*7c478bd9Sstevel@tonic-gate   retval = asn1_decode_integer(buf,&n);\
302*7c478bd9Sstevel@tonic-gate   if(retval) return retval;\
303*7c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
304*7c478bd9Sstevel@tonic-gate   return 0;\
305*7c478bd9Sstevel@tonic-gate }
306*7c478bd9Sstevel@tonic-gate #define unsigned_integer_convert(fname,ktype)\
307*7c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
308*7c478bd9Sstevel@tonic-gate {\
309*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
310*7c478bd9Sstevel@tonic-gate   unsigned long n;\
311*7c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);\
312*7c478bd9Sstevel@tonic-gate   if(retval) return retval;\
313*7c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
314*7c478bd9Sstevel@tonic-gate   return 0;\
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int,int)
317*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int32,krb5_int32)
318*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_kvno,krb5_kvno)
319*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_enctype,krb5_enctype)
320*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
321*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_octet,krb5_octet)
322*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_addrtype,krb5_addrtype)
323*7c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
324*7c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
325*7c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
328*7c478bd9Sstevel@tonic-gate {
329*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;
330*7c478bd9Sstevel@tonic-gate   unsigned long n;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate   retval = asn1_decode_maybe_unsigned(buf, &n);
333*7c478bd9Sstevel@tonic-gate   if (retval) return retval;
334*7c478bd9Sstevel@tonic-gate   *val = (krb5_ui_4)n & 0xffffffff;
335*7c478bd9Sstevel@tonic-gate   return 0;
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
339*7c478bd9Sstevel@tonic-gate {
340*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;
341*7c478bd9Sstevel@tonic-gate   unsigned long n;
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);
344*7c478bd9Sstevel@tonic-gate   if(retval) return retval;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate   *val = (krb5_msgtype) n;
347*7c478bd9Sstevel@tonic-gate   return 0;
348*7c478bd9Sstevel@tonic-gate }
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate /* structures */
352*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val)
353*7c478bd9Sstevel@tonic-gate {
354*7c478bd9Sstevel@tonic-gate   return asn1_decode_generalstring(buf,
355*7c478bd9Sstevel@tonic-gate 				   (uint32_t *)&((*val)->realm.length),
356*7c478bd9Sstevel@tonic-gate 				   &((*val)->realm.data));
357*7c478bd9Sstevel@tonic-gate }
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
360*7c478bd9Sstevel@tonic-gate {
361*7c478bd9Sstevel@tonic-gate   setup();
362*7c478bd9Sstevel@tonic-gate   { begin_structure();
363*7c478bd9Sstevel@tonic-gate     get_field((*val)->type,0,asn1_decode_int32);
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
366*7c478bd9Sstevel@tonic-gate       while(asn1buf_remains(&seqbuf,seqofindef) > 0){
367*7c478bd9Sstevel@tonic-gate 	size++;
368*7c478bd9Sstevel@tonic-gate 	if ((*val)->data == NULL)
369*7c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
370*7c478bd9Sstevel@tonic-gate 	else
371*7c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)realloc((*val)->data,
372*7c478bd9Sstevel@tonic-gate 					     size*sizeof(krb5_data));
373*7c478bd9Sstevel@tonic-gate 	if((*val)->data == NULL) return ENOMEM;
374*7c478bd9Sstevel@tonic-gate 	retval = asn1_decode_generalstring(&seqbuf,
375*7c478bd9Sstevel@tonic-gate 			   (uint32_t *)&((*val)->data[size-1].length),
376*7c478bd9Sstevel@tonic-gate 			   &((*val)->data[size-1].data));
377*7c478bd9Sstevel@tonic-gate 	if(retval) return retval;
378*7c478bd9Sstevel@tonic-gate       }
379*7c478bd9Sstevel@tonic-gate       (*val)->length = size;
380*7c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
381*7c478bd9Sstevel@tonic-gate     }
382*7c478bd9Sstevel@tonic-gate     if (indef) {
383*7c478bd9Sstevel@tonic-gate 	get_eoc();
384*7c478bd9Sstevel@tonic-gate     }
385*7c478bd9Sstevel@tonic-gate     next_tag();
386*7c478bd9Sstevel@tonic-gate     end_structure();
387*7c478bd9Sstevel@tonic-gate     (*val)->magic = KV5M_PRINCIPAL;
388*7c478bd9Sstevel@tonic-gate   }
389*7c478bd9Sstevel@tonic-gate   cleanup();
390*7c478bd9Sstevel@tonic-gate }
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val)
393*7c478bd9Sstevel@tonic-gate {
394*7c478bd9Sstevel@tonic-gate   setup();
395*7c478bd9Sstevel@tonic-gate   { begin_structure();
396*7c478bd9Sstevel@tonic-gate     get_field(val->checksum_type,0,asn1_decode_cksumtype);
397*7c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
398*7c478bd9Sstevel@tonic-gate     end_structure();
399*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_CHECKSUM;
400*7c478bd9Sstevel@tonic-gate   }
401*7c478bd9Sstevel@tonic-gate   cleanup();
402*7c478bd9Sstevel@tonic-gate }
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val)
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate   setup();
407*7c478bd9Sstevel@tonic-gate   { begin_structure();
408*7c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
409*7c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
410*7c478bd9Sstevel@tonic-gate     end_structure();
411*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_KEYBLOCK;
412*7c478bd9Sstevel@tonic-gate   }
413*7c478bd9Sstevel@tonic-gate   cleanup();
414*7c478bd9Sstevel@tonic-gate }
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val)
417*7c478bd9Sstevel@tonic-gate {
418*7c478bd9Sstevel@tonic-gate   setup();
419*7c478bd9Sstevel@tonic-gate   { begin_structure();
420*7c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
421*7c478bd9Sstevel@tonic-gate     opt_field(val->kvno,1,asn1_decode_kvno,0);
422*7c478bd9Sstevel@tonic-gate     get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
423*7c478bd9Sstevel@tonic-gate     end_structure();
424*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_DATA;
425*7c478bd9Sstevel@tonic-gate   }
426*7c478bd9Sstevel@tonic-gate   cleanup();
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
430*7c478bd9Sstevel@tonic-gate {
431*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;
432*7c478bd9Sstevel@tonic-gate   asn1_octet unused, o;
433*7c478bd9Sstevel@tonic-gate   taginfo t;
434*7c478bd9Sstevel@tonic-gate   int i;
435*7c478bd9Sstevel@tonic-gate   krb5_flags f=0;
436*7c478bd9Sstevel@tonic-gate   unsigned int length;
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(buf, &t);
439*7c478bd9Sstevel@tonic-gate   if (retval) return retval;
440*7c478bd9Sstevel@tonic-gate   if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
441*7c478bd9Sstevel@tonic-gate       t.tagnum != ASN1_BITSTRING)
442*7c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
443*7c478bd9Sstevel@tonic-gate   length = t.length;
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate   retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
446*7c478bd9Sstevel@tonic-gate   if(retval) return retval;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate   /* Number of unused bits must be between 0 and 7. */
449*7c478bd9Sstevel@tonic-gate   if (unused > 7) return ASN1_BAD_FORMAT;
450*7c478bd9Sstevel@tonic-gate   length--;
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate   for(i = 0; i < length; i++) {
453*7c478bd9Sstevel@tonic-gate     retval = asn1buf_remove_octet(buf,&o);
454*7c478bd9Sstevel@tonic-gate     if(retval) return retval;
455*7c478bd9Sstevel@tonic-gate     /* ignore bits past number 31 */
456*7c478bd9Sstevel@tonic-gate     if (i < 4)
457*7c478bd9Sstevel@tonic-gate       f = (f<<8) | ((krb5_flags)o&0xFF);
458*7c478bd9Sstevel@tonic-gate   }
459*7c478bd9Sstevel@tonic-gate   if (length <= 4) {
460*7c478bd9Sstevel@tonic-gate     /* Mask out unused bits, but only if necessary. */
461*7c478bd9Sstevel@tonic-gate     f &= ~(krb5_flags)0 << unused;
462*7c478bd9Sstevel@tonic-gate   }
463*7c478bd9Sstevel@tonic-gate   /* left-justify */
464*7c478bd9Sstevel@tonic-gate   if (length < 4)
465*7c478bd9Sstevel@tonic-gate     f <<= (4 - length) * 8;
466*7c478bd9Sstevel@tonic-gate   *val = f;
467*7c478bd9Sstevel@tonic-gate   return 0;
468*7c478bd9Sstevel@tonic-gate }
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val)
471*7c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val)
474*7c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val)
477*7c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val)
480*7c478bd9Sstevel@tonic-gate {
481*7c478bd9Sstevel@tonic-gate   setup();
482*7c478bd9Sstevel@tonic-gate   { begin_structure();
483*7c478bd9Sstevel@tonic-gate     get_field(val->tr_type,0,asn1_decode_octet);
484*7c478bd9Sstevel@tonic-gate     get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
485*7c478bd9Sstevel@tonic-gate     end_structure();
486*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_TRANSITED;
487*7c478bd9Sstevel@tonic-gate   }
488*7c478bd9Sstevel@tonic-gate   cleanup();
489*7c478bd9Sstevel@tonic-gate }
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val)
492*7c478bd9Sstevel@tonic-gate {
493*7c478bd9Sstevel@tonic-gate   setup();
494*7c478bd9Sstevel@tonic-gate   { begin_structure();
495*7c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
496*7c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
497*7c478bd9Sstevel@tonic-gate     get_field(val->last_req,1,asn1_decode_last_req);
498*7c478bd9Sstevel@tonic-gate     get_field(val->nonce,2,asn1_decode_int32);
499*7c478bd9Sstevel@tonic-gate     opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
500*7c478bd9Sstevel@tonic-gate     get_field(val->flags,4,asn1_decode_ticket_flags);
501*7c478bd9Sstevel@tonic-gate     get_field(val->times.authtime,5,asn1_decode_kerberos_time);
502*7c478bd9Sstevel@tonic-gate     /* Set to authtime if missing */
503*7c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime);
504*7c478bd9Sstevel@tonic-gate     get_field(val->times.endtime,7,asn1_decode_kerberos_time);
505*7c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
506*7c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
507*7c478bd9Sstevel@tonic-gate     get_field(val->server,9,asn1_decode_realm);
508*7c478bd9Sstevel@tonic-gate     get_field(val->server,10,asn1_decode_principal_name);
509*7c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
510*7c478bd9Sstevel@tonic-gate     end_structure();
511*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_KDC_REP_PART;
512*7c478bd9Sstevel@tonic-gate   }
513*7c478bd9Sstevel@tonic-gate   cleanup();
514*7c478bd9Sstevel@tonic-gate }
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
517*7c478bd9Sstevel@tonic-gate {
518*7c478bd9Sstevel@tonic-gate   setup();
519*7c478bd9Sstevel@tonic-gate   unsigned int applen;
520*7c478bd9Sstevel@tonic-gate   apptag(1);
521*7c478bd9Sstevel@tonic-gate   { begin_structure();
522*7c478bd9Sstevel@tonic-gate     { krb5_kvno vno;
523*7c478bd9Sstevel@tonic-gate       get_field(vno,0,asn1_decode_kvno);
524*7c478bd9Sstevel@tonic-gate       if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
525*7c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
526*7c478bd9Sstevel@tonic-gate     get_field(val->server,1,asn1_decode_realm);
527*7c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_principal_name);
528*7c478bd9Sstevel@tonic-gate     get_field(val->enc_part,3,asn1_decode_encrypted_data);
529*7c478bd9Sstevel@tonic-gate     end_structure();
530*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_TICKET;
531*7c478bd9Sstevel@tonic-gate   }
532*7c478bd9Sstevel@tonic-gate   if (!applen) {
533*7c478bd9Sstevel@tonic-gate       taginfo t;
534*7c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t);
535*7c478bd9Sstevel@tonic-gate       if (retval) {
536*7c478bd9Sstevel@tonic-gate 	  free_field(val->server);
537*7c478bd9Sstevel@tonic-gate 	  return retval;
538*7c478bd9Sstevel@tonic-gate       }
539*7c478bd9Sstevel@tonic-gate   }
540*7c478bd9Sstevel@tonic-gate   cleanup();
541*7c478bd9Sstevel@tonic-gate }
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val)
544*7c478bd9Sstevel@tonic-gate {
545*7c478bd9Sstevel@tonic-gate   setup();
546*7c478bd9Sstevel@tonic-gate   { begin_structure();
547*7c478bd9Sstevel@tonic-gate     { krb5_kvno kvno;
548*7c478bd9Sstevel@tonic-gate       get_field(kvno,1,asn1_decode_kvno);
549*7c478bd9Sstevel@tonic-gate       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
550*7c478bd9Sstevel@tonic-gate     get_field(val->msg_type,2,asn1_decode_msgtype);
551*7c478bd9Sstevel@tonic-gate     opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
552*7c478bd9Sstevel@tonic-gate     get_field(*val,4,asn1_decode_kdc_req_body);
553*7c478bd9Sstevel@tonic-gate     end_structure();
554*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
555*7c478bd9Sstevel@tonic-gate   }
556*7c478bd9Sstevel@tonic-gate   cleanup();
557*7c478bd9Sstevel@tonic-gate }
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val)
560*7c478bd9Sstevel@tonic-gate {
561*7c478bd9Sstevel@tonic-gate   setup();
562*7c478bd9Sstevel@tonic-gate   {
563*7c478bd9Sstevel@tonic-gate     krb5_principal psave;
564*7c478bd9Sstevel@tonic-gate     begin_structure();
565*7c478bd9Sstevel@tonic-gate     get_field(val->kdc_options,0,asn1_decode_kdc_options);
566*7c478bd9Sstevel@tonic-gate     if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
567*7c478bd9Sstevel@tonic-gate     opt_field(val->client,1,asn1_decode_principal_name,NULL);
568*7c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
569*7c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_realm);
570*7c478bd9Sstevel@tonic-gate     if(val->client != NULL){
571*7c478bd9Sstevel@tonic-gate       retval = asn1_krb5_realm_copy(val->client,val->server);
572*7c478bd9Sstevel@tonic-gate       if(retval) {
573*7c478bd9Sstevel@tonic-gate 	  free_field(val->server);
574*7c478bd9Sstevel@tonic-gate 	  free_field(val->client);
575*7c478bd9Sstevel@tonic-gate 	  return retval; }
576*7c478bd9Sstevel@tonic-gate       }
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate     /* If opt_field server is missing, memory reference to server is
580*7c478bd9Sstevel@tonic-gate        lost and results in memory leak */
581*7c478bd9Sstevel@tonic-gate     psave = val->server;
582*7c478bd9Sstevel@tonic-gate     opt_field(val->server,3,asn1_decode_principal_name,NULL);
583*7c478bd9Sstevel@tonic-gate     if(val->server == NULL){
584*7c478bd9Sstevel@tonic-gate       if(psave->realm.data) {
585*7c478bd9Sstevel@tonic-gate 	free(psave->realm.data);
586*7c478bd9Sstevel@tonic-gate 	psave->realm.data = NULL;
587*7c478bd9Sstevel@tonic-gate 	psave->realm.length=0;
588*7c478bd9Sstevel@tonic-gate       }
589*7c478bd9Sstevel@tonic-gate       free(psave);
590*7c478bd9Sstevel@tonic-gate     }
591*7c478bd9Sstevel@tonic-gate     opt_field(val->from,4,asn1_decode_kerberos_time,0);
592*7c478bd9Sstevel@tonic-gate     get_field(val->till,5,asn1_decode_kerberos_time);
593*7c478bd9Sstevel@tonic-gate     opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
594*7c478bd9Sstevel@tonic-gate     get_field(val->nonce,7,asn1_decode_int32);
595*7c478bd9Sstevel@tonic-gate     get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype);
596*7c478bd9Sstevel@tonic-gate     opt_field(val->addresses,9,asn1_decode_host_addresses,0);
597*7c478bd9Sstevel@tonic-gate     if(tagnum == 10){
598*7c478bd9Sstevel@tonic-gate       get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
599*7c478bd9Sstevel@tonic-gate     else{
600*7c478bd9Sstevel@tonic-gate       val->authorization_data.magic = KV5M_ENC_DATA;
601*7c478bd9Sstevel@tonic-gate       val->authorization_data.enctype = 0;
602*7c478bd9Sstevel@tonic-gate       val->authorization_data.kvno = 0;
603*7c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.data = NULL;
604*7c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.length = 0;
605*7c478bd9Sstevel@tonic-gate     }
606*7c478bd9Sstevel@tonic-gate     opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
607*7c478bd9Sstevel@tonic-gate     end_structure();
608*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
609*7c478bd9Sstevel@tonic-gate   }
610*7c478bd9Sstevel@tonic-gate   cleanup();
611*7c478bd9Sstevel@tonic-gate }
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val)
614*7c478bd9Sstevel@tonic-gate {
615*7c478bd9Sstevel@tonic-gate   setup();
616*7c478bd9Sstevel@tonic-gate   { begin_structure();
617*7c478bd9Sstevel@tonic-gate     get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
618*7c478bd9Sstevel@tonic-gate     opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
619*7c478bd9Sstevel@tonic-gate     opt_field(val->usec,2,asn1_decode_int32,0);
620*7c478bd9Sstevel@tonic-gate     opt_field(val->seq_number,3,asn1_decode_seqnum,0);
621*7c478bd9Sstevel@tonic-gate     alloc_field(val->s_address,krb5_address);
622*7c478bd9Sstevel@tonic-gate     get_field(*(val->s_address),4,asn1_decode_host_address);
623*7c478bd9Sstevel@tonic-gate     if(tagnum == 5){
624*7c478bd9Sstevel@tonic-gate       alloc_field(val->r_address,krb5_address);
625*7c478bd9Sstevel@tonic-gate       get_field(*(val->r_address),5,asn1_decode_host_address);
626*7c478bd9Sstevel@tonic-gate     } else val->r_address = NULL;
627*7c478bd9Sstevel@tonic-gate     end_structure();
628*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAFE;
629*7c478bd9Sstevel@tonic-gate   }
630*7c478bd9Sstevel@tonic-gate   cleanup();
631*7c478bd9Sstevel@tonic-gate }
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val)
634*7c478bd9Sstevel@tonic-gate {
635*7c478bd9Sstevel@tonic-gate   setup();
636*7c478bd9Sstevel@tonic-gate   { begin_structure();
637*7c478bd9Sstevel@tonic-gate     get_field(val->addrtype,0,asn1_decode_addrtype);
638*7c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
639*7c478bd9Sstevel@tonic-gate     end_structure();
640*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ADDRESS;
641*7c478bd9Sstevel@tonic-gate   }
642*7c478bd9Sstevel@tonic-gate   cleanup();
643*7c478bd9Sstevel@tonic-gate }
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val)
646*7c478bd9Sstevel@tonic-gate {
647*7c478bd9Sstevel@tonic-gate   setup();
648*7c478bd9Sstevel@tonic-gate   { begin_structure();
649*7c478bd9Sstevel@tonic-gate     { krb5_kvno pvno;
650*7c478bd9Sstevel@tonic-gate       get_field(pvno,0,asn1_decode_kvno);
651*7c478bd9Sstevel@tonic-gate       if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
652*7c478bd9Sstevel@tonic-gate     get_field(val->msg_type,1,asn1_decode_msgtype);
653*7c478bd9Sstevel@tonic-gate     opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
654*7c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
655*7c478bd9Sstevel@tonic-gate     get_field(val->client,3,asn1_decode_realm);
656*7c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_principal_name);
657*7c478bd9Sstevel@tonic-gate     alloc_field(val->ticket,krb5_ticket);
658*7c478bd9Sstevel@tonic-gate     get_field(*(val->ticket),5,asn1_decode_ticket);
659*7c478bd9Sstevel@tonic-gate     get_field(val->enc_part,6,asn1_decode_encrypted_data);
660*7c478bd9Sstevel@tonic-gate     end_structure();
661*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REP;
662*7c478bd9Sstevel@tonic-gate   }
663*7c478bd9Sstevel@tonic-gate   cleanup();
664*7c478bd9Sstevel@tonic-gate }
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate /* arrays */
668*7c478bd9Sstevel@tonic-gate #define get_element(element,decoder)\
669*7c478bd9Sstevel@tonic-gate retval = decoder(&seqbuf,element);\
670*7c478bd9Sstevel@tonic-gate if(retval) return retval
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate #define array_append(array,size,element,type)\
673*7c478bd9Sstevel@tonic-gate size++;\
674*7c478bd9Sstevel@tonic-gate if (*(array) == NULL)\
675*7c478bd9Sstevel@tonic-gate      *(array) = (type**)malloc((size+1)*sizeof(type*));\
676*7c478bd9Sstevel@tonic-gate else\
677*7c478bd9Sstevel@tonic-gate   *(array) = (type**)realloc(*(array),\
678*7c478bd9Sstevel@tonic-gate 			     (size+1)*sizeof(type*));\
679*7c478bd9Sstevel@tonic-gate if(*(array) == NULL) return ENOMEM;\
680*7c478bd9Sstevel@tonic-gate (*(array))[(size)-1] = elt
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate #define decode_array_body(type,decoder)\
683*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
684*7c478bd9Sstevel@tonic-gate   type *elt;\
685*7c478bd9Sstevel@tonic-gate \
686*7c478bd9Sstevel@tonic-gate   { sequence_of(buf);\
687*7c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){\
688*7c478bd9Sstevel@tonic-gate       alloc_field(elt,type);\
689*7c478bd9Sstevel@tonic-gate       get_element(elt,decoder);\
690*7c478bd9Sstevel@tonic-gate       array_append(val,size,elt,type);\
691*7c478bd9Sstevel@tonic-gate     }\
692*7c478bd9Sstevel@tonic-gate     if (*val == NULL)\
693*7c478bd9Sstevel@tonic-gate 	*val = (type **)malloc(sizeof(type*));\
694*7c478bd9Sstevel@tonic-gate     (*val)[size] = NULL;\
695*7c478bd9Sstevel@tonic-gate     end_sequence_of(buf);\
696*7c478bd9Sstevel@tonic-gate   }\
697*7c478bd9Sstevel@tonic-gate   cleanup()
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val)
701*7c478bd9Sstevel@tonic-gate {
702*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
703*7c478bd9Sstevel@tonic-gate }
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val)
706*7c478bd9Sstevel@tonic-gate {
707*7c478bd9Sstevel@tonic-gate   setup();
708*7c478bd9Sstevel@tonic-gate   { begin_structure();
709*7c478bd9Sstevel@tonic-gate     get_field(val->ad_type,0,asn1_decode_authdatatype);
710*7c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
711*7c478bd9Sstevel@tonic-gate     end_structure();
712*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_AUTHDATA;
713*7c478bd9Sstevel@tonic-gate   }
714*7c478bd9Sstevel@tonic-gate   cleanup();
715*7c478bd9Sstevel@tonic-gate }
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val)
718*7c478bd9Sstevel@tonic-gate {
719*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_address,asn1_decode_host_address);
720*7c478bd9Sstevel@tonic-gate }
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val)
723*7c478bd9Sstevel@tonic-gate {
724*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_ticket,asn1_decode_ticket);
725*7c478bd9Sstevel@tonic-gate }
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val)
728*7c478bd9Sstevel@tonic-gate {
729*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
730*7c478bd9Sstevel@tonic-gate }
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val)
733*7c478bd9Sstevel@tonic-gate {
734*7c478bd9Sstevel@tonic-gate   setup();
735*7c478bd9Sstevel@tonic-gate   { begin_structure();
736*7c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
737*7c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
738*7c478bd9Sstevel@tonic-gate     if(tagnum == 1){
739*7c478bd9Sstevel@tonic-gate       alloc_field(val->client,krb5_principal_data);
740*7c478bd9Sstevel@tonic-gate       opt_field(val->client,1,asn1_decode_realm,NULL);
741*7c478bd9Sstevel@tonic-gate       opt_field(val->client,2,asn1_decode_principal_name,NULL); }
742*7c478bd9Sstevel@tonic-gate     opt_field(val->flags,3,asn1_decode_ticket_flags,0);
743*7c478bd9Sstevel@tonic-gate     opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
744*7c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
745*7c478bd9Sstevel@tonic-gate     opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
746*7c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
747*7c478bd9Sstevel@tonic-gate     if(tagnum == 8){
748*7c478bd9Sstevel@tonic-gate       alloc_field(val->server,krb5_principal_data);
749*7c478bd9Sstevel@tonic-gate       opt_field(val->server,8,asn1_decode_realm,NULL);
750*7c478bd9Sstevel@tonic-gate       opt_field(val->server,9,asn1_decode_principal_name,NULL); }
751*7c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
752*7c478bd9Sstevel@tonic-gate     end_structure();
753*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_CRED_INFO;
754*7c478bd9Sstevel@tonic-gate   }
755*7c478bd9Sstevel@tonic-gate   cleanup();
756*7c478bd9Sstevel@tonic-gate }
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val)
759*7c478bd9Sstevel@tonic-gate {
760*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_pa_data,asn1_decode_pa_data);
761*7c478bd9Sstevel@tonic-gate }
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val)
764*7c478bd9Sstevel@tonic-gate {
765*7c478bd9Sstevel@tonic-gate   setup();
766*7c478bd9Sstevel@tonic-gate   { begin_structure();
767*7c478bd9Sstevel@tonic-gate     get_field(val->pa_type,1,asn1_decode_int32);
768*7c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
769*7c478bd9Sstevel@tonic-gate     end_structure();
770*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_PA_DATA;
771*7c478bd9Sstevel@tonic-gate   }
772*7c478bd9Sstevel@tonic-gate   cleanup();
773*7c478bd9Sstevel@tonic-gate }
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val)
776*7c478bd9Sstevel@tonic-gate {
777*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
778*7c478bd9Sstevel@tonic-gate }
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val)
781*7c478bd9Sstevel@tonic-gate {
782*7c478bd9Sstevel@tonic-gate   setup();
783*7c478bd9Sstevel@tonic-gate   { begin_structure();
784*7c478bd9Sstevel@tonic-gate     get_field(val->lr_type,0,asn1_decode_int32);
785*7c478bd9Sstevel@tonic-gate     get_field(val->value,1,asn1_decode_kerberos_time);
786*7c478bd9Sstevel@tonic-gate     end_structure();
787*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_LAST_REQ_ENTRY;
788*7c478bd9Sstevel@tonic-gate #ifdef KRB5_GENEROUS_LR_TYPE
789*7c478bd9Sstevel@tonic-gate     /* If we are only a single byte wide and negative - fill in the
790*7c478bd9Sstevel@tonic-gate        other bits */
791*7c478bd9Sstevel@tonic-gate     if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U;
792*7c478bd9Sstevel@tonic-gate #endif
793*7c478bd9Sstevel@tonic-gate   }
794*7c478bd9Sstevel@tonic-gate   cleanup();
795*7c478bd9Sstevel@tonic-gate }
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val)
798*7c478bd9Sstevel@tonic-gate {
799*7c478bd9Sstevel@tonic-gate   asn1_error_code retval;
800*7c478bd9Sstevel@tonic-gate   { sequence_of(buf);
801*7c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){
802*7c478bd9Sstevel@tonic-gate       size++;
803*7c478bd9Sstevel@tonic-gate       if (*val == NULL)
804*7c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
805*7c478bd9Sstevel@tonic-gate       else
806*7c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
807*7c478bd9Sstevel@tonic-gate       if(*val == NULL) return ENOMEM;
808*7c478bd9Sstevel@tonic-gate       retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
809*7c478bd9Sstevel@tonic-gate       if(retval) return retval;
810*7c478bd9Sstevel@tonic-gate     }
811*7c478bd9Sstevel@tonic-gate     *num = size;
812*7c478bd9Sstevel@tonic-gate     end_sequence_of(buf);
813*7c478bd9Sstevel@tonic-gate   }
814*7c478bd9Sstevel@tonic-gate   cleanup();
815*7c478bd9Sstevel@tonic-gate }
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val)
818*7c478bd9Sstevel@tonic-gate {
819*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_checksum, asn1_decode_checksum);
820*7c478bd9Sstevel@tonic-gate }
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val )
823*7c478bd9Sstevel@tonic-gate {
824*7c478bd9Sstevel@tonic-gate   setup();
825*7c478bd9Sstevel@tonic-gate   { begin_structure();
826*7c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
827*7c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
828*7c478bd9Sstevel@tonic-gate 	    char *s = (char *)val->salt;
829*7c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length, s, 1, asn1_decode_generalstring);
830*7c478bd9Sstevel@tonic-gate     } else {
831*7c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
832*7c478bd9Sstevel@tonic-gate 	    val->salt = 0;
833*7c478bd9Sstevel@tonic-gate     }
834*7c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
835*7c478bd9Sstevel@tonic-gate       krb5_octet *params ;
836*7c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
837*7c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
838*7c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
839*7c478bd9Sstevel@tonic-gate     } else {
840*7c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
841*7c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
842*7c478bd9Sstevel@tonic-gate     }
843*7c478bd9Sstevel@tonic-gate     end_structure();
844*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
845*7c478bd9Sstevel@tonic-gate   }
846*7c478bd9Sstevel@tonic-gate   cleanup();
847*7c478bd9Sstevel@tonic-gate }
848*7c478bd9Sstevel@tonic-gate 
849*7c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val )
850*7c478bd9Sstevel@tonic-gate {
851*7c478bd9Sstevel@tonic-gate   setup();
852*7c478bd9Sstevel@tonic-gate   { begin_structure();
853*7c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
854*7c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
855*7c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
856*7c478bd9Sstevel@tonic-gate     } else {
857*7c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
858*7c478bd9Sstevel@tonic-gate 	    val->salt = 0;
859*7c478bd9Sstevel@tonic-gate     }
860*7c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
861*7c478bd9Sstevel@tonic-gate       krb5_octet *params ;
862*7c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
863*7c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
864*7c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
865*7c478bd9Sstevel@tonic-gate     } else {
866*7c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
867*7c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
868*7c478bd9Sstevel@tonic-gate     }
869*7c478bd9Sstevel@tonic-gate     end_structure();
870*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
871*7c478bd9Sstevel@tonic-gate   }
872*7c478bd9Sstevel@tonic-gate   cleanup();
873*7c478bd9Sstevel@tonic-gate }
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val )
876*7c478bd9Sstevel@tonic-gate {
877*7c478bd9Sstevel@tonic-gate   setup();
878*7c478bd9Sstevel@tonic-gate   { begin_structure();
879*7c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
880*7c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
881*7c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
882*7c478bd9Sstevel@tonic-gate     } else {
883*7c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
884*7c478bd9Sstevel@tonic-gate 	    val->salt = 0;
885*7c478bd9Sstevel@tonic-gate     }
886*7c478bd9Sstevel@tonic-gate     val->s2kparams.data = NULL;
887*7c478bd9Sstevel@tonic-gate     val->s2kparams.length = 0;
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate     end_structure();
890*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
891*7c478bd9Sstevel@tonic-gate   }
892*7c478bd9Sstevel@tonic-gate   cleanup();
893*7c478bd9Sstevel@tonic-gate }
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val )
896*7c478bd9Sstevel@tonic-gate {
897*7c478bd9Sstevel@tonic-gate   decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry);
898*7c478bd9Sstevel@tonic-gate }
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val ,
901*7c478bd9Sstevel@tonic-gate 					krb5_boolean v1_3_behavior)
902*7c478bd9Sstevel@tonic-gate {
903*7c478bd9Sstevel@tonic-gate     if (v1_3_behavior) {
904*7c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
905*7c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry_1_3);
906*7c478bd9Sstevel@tonic-gate     } else {
907*7c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
908*7c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry);
909*7c478bd9Sstevel@tonic-gate     }
910*7c478bd9Sstevel@tonic-gate }
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val)
913*7c478bd9Sstevel@tonic-gate {
914*7c478bd9Sstevel@tonic-gate   setup();
915*7c478bd9Sstevel@tonic-gate   { begin_structure();
916*7c478bd9Sstevel@tonic-gate     alloc_field(val->passwd,krb5_data);
917*7c478bd9Sstevel@tonic-gate     get_lenfield(val->passwd->length,val->passwd->data,
918*7c478bd9Sstevel@tonic-gate 		 0,asn1_decode_charstring);
919*7c478bd9Sstevel@tonic-gate     val->passwd->magic = KV5M_DATA;
920*7c478bd9Sstevel@tonic-gate     alloc_field(val->phrase,krb5_data);
921*7c478bd9Sstevel@tonic-gate     get_lenfield(val->phrase->length,val->phrase->data,
922*7c478bd9Sstevel@tonic-gate 		 1,asn1_decode_charstring);
923*7c478bd9Sstevel@tonic-gate     val->phrase->magic = KV5M_DATA;
924*7c478bd9Sstevel@tonic-gate     end_structure();
925*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_PASSWD_PHRASE_ELEMENT;
926*7c478bd9Sstevel@tonic-gate   }
927*7c478bd9Sstevel@tonic-gate   cleanup();
928*7c478bd9Sstevel@tonic-gate }
929*7c478bd9Sstevel@tonic-gate 
930*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val)
931*7c478bd9Sstevel@tonic-gate {
932*7c478bd9Sstevel@tonic-gate   decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
933*7c478bd9Sstevel@tonic-gate }
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val)
936*7c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
937*7c478bd9Sstevel@tonic-gate 
938*7c478bd9Sstevel@tonic-gate #define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn)
939*7c478bd9Sstevel@tonic-gate #define opt_cksum(var,tagexpect,decoder)\
940*7c478bd9Sstevel@tonic-gate if(tagnum == (tagexpect)){\
941*7c478bd9Sstevel@tonic-gate   get_field_body(var,decoder); }\
942*7c478bd9Sstevel@tonic-gate else var.length = 0
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val)
945*7c478bd9Sstevel@tonic-gate {
946*7c478bd9Sstevel@tonic-gate   setup();
947*7c478bd9Sstevel@tonic-gate   { begin_structure();
948*7c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
949*7c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
950*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
951*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
952*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
953*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
954*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
955*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
956*7c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,8,asn1_decode_int32,0);
957*7c478bd9Sstevel@tonic-gate     opt_cksum(val->sam_cksum,9,asn1_decode_checksum);
958*7c478bd9Sstevel@tonic-gate     end_structure();
959*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
960*7c478bd9Sstevel@tonic-gate   }
961*7c478bd9Sstevel@tonic-gate   cleanup();
962*7c478bd9Sstevel@tonic-gate }
963*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val)
964*7c478bd9Sstevel@tonic-gate {
965*7c478bd9Sstevel@tonic-gate   setup();
966*7c478bd9Sstevel@tonic-gate   { char *save, *end;
967*7c478bd9Sstevel@tonic-gate     size_t alloclen;
968*7c478bd9Sstevel@tonic-gate     begin_structure();
969*7c478bd9Sstevel@tonic-gate     if (tagnum != 0) return ASN1_MISSING_FIELD;
970*7c478bd9Sstevel@tonic-gate     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
971*7c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
972*7c478bd9Sstevel@tonic-gate     save = subbuf.next;
973*7c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
974*7c478bd9Sstevel@tonic-gate       unused_var(size);
975*7c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
976*7c478bd9Sstevel@tonic-gate     }
977*7c478bd9Sstevel@tonic-gate     end = subbuf.next;
978*7c478bd9Sstevel@tonic-gate     alloclen = end - save;
979*7c478bd9Sstevel@tonic-gate     if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL)
980*7c478bd9Sstevel@tonic-gate       return ENOMEM;
981*7c478bd9Sstevel@tonic-gate     val->sam_challenge_2_body.length = alloclen;
982*7c478bd9Sstevel@tonic-gate     memcpy(val->sam_challenge_2_body.data, save, alloclen);
983*7c478bd9Sstevel@tonic-gate     next_tag();
984*7c478bd9Sstevel@tonic-gate     get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum);
985*7c478bd9Sstevel@tonic-gate     end_structure();
986*7c478bd9Sstevel@tonic-gate   }
987*7c478bd9Sstevel@tonic-gate   cleanup();
988*7c478bd9Sstevel@tonic-gate }
989*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val)
990*7c478bd9Sstevel@tonic-gate {
991*7c478bd9Sstevel@tonic-gate   setup();
992*7c478bd9Sstevel@tonic-gate   { begin_structure();
993*7c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
994*7c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
995*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
996*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
997*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
998*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
999*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
1000*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
1001*7c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,8,asn1_decode_int32);
1002*7c478bd9Sstevel@tonic-gate     get_field(val->sam_etype, 9, asn1_decode_int32);
1003*7c478bd9Sstevel@tonic-gate     end_structure();
1004*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
1005*7c478bd9Sstevel@tonic-gate   }
1006*7c478bd9Sstevel@tonic-gate   cleanup();
1007*7c478bd9Sstevel@tonic-gate }
1008*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val)
1009*7c478bd9Sstevel@tonic-gate {
1010*7c478bd9Sstevel@tonic-gate   setup();
1011*7c478bd9Sstevel@tonic-gate   { begin_structure();
1012*7c478bd9Sstevel@tonic-gate     /* alloc_field(val->sam_key,krb5_keyblock); */
1013*7c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
1014*7c478bd9Sstevel@tonic-gate     end_structure();
1015*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_KEY;
1016*7c478bd9Sstevel@tonic-gate   }
1017*7c478bd9Sstevel@tonic-gate   cleanup();
1018*7c478bd9Sstevel@tonic-gate }
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val)
1021*7c478bd9Sstevel@tonic-gate {
1022*7c478bd9Sstevel@tonic-gate   setup();
1023*7c478bd9Sstevel@tonic-gate   { begin_structure();
1024*7c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,0,asn1_decode_int32,0);
1025*7c478bd9Sstevel@tonic-gate     opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0);
1026*7c478bd9Sstevel@tonic-gate     opt_field(val->sam_usec,2,asn1_decode_int32,0);
1027*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,3,asn1_decode_charstring);
1028*7c478bd9Sstevel@tonic-gate     end_structure();
1029*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC;
1030*7c478bd9Sstevel@tonic-gate   }
1031*7c478bd9Sstevel@tonic-gate   cleanup();
1032*7c478bd9Sstevel@tonic-gate }
1033*7c478bd9Sstevel@tonic-gate 
1034*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val)
1035*7c478bd9Sstevel@tonic-gate {
1036*7c478bd9Sstevel@tonic-gate   setup();
1037*7c478bd9Sstevel@tonic-gate   { begin_structure();
1038*7c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,0,asn1_decode_int32);
1039*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,1,asn1_decode_charstring);
1040*7c478bd9Sstevel@tonic-gate     end_structure();
1041*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
1042*7c478bd9Sstevel@tonic-gate   }
1043*7c478bd9Sstevel@tonic-gate   cleanup();
1044*7c478bd9Sstevel@tonic-gate }
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate #define opt_encfield(fld,tag,fn) \
1047*7c478bd9Sstevel@tonic-gate     if(tagnum == tag){ \
1048*7c478bd9Sstevel@tonic-gate       get_field(fld,tag,fn); } \
1049*7c478bd9Sstevel@tonic-gate     else{\
1050*7c478bd9Sstevel@tonic-gate       fld.magic = 0;\
1051*7c478bd9Sstevel@tonic-gate       fld.enctype = 0;\
1052*7c478bd9Sstevel@tonic-gate       fld.kvno = 0;\
1053*7c478bd9Sstevel@tonic-gate       fld.ciphertext.data = NULL;\
1054*7c478bd9Sstevel@tonic-gate       fld.ciphertext.length = 0;\
1055*7c478bd9Sstevel@tonic-gate     }
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val)
1058*7c478bd9Sstevel@tonic-gate {
1059*7c478bd9Sstevel@tonic-gate   setup();
1060*7c478bd9Sstevel@tonic-gate   { begin_structure();
1061*7c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
1062*7c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1063*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
1064*7c478bd9Sstevel@tonic-gate     opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data);
1065*7c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data);
1066*7c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,5,asn1_decode_int32,0);
1067*7c478bd9Sstevel@tonic-gate     opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0);
1068*7c478bd9Sstevel@tonic-gate     end_structure();
1069*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
1070*7c478bd9Sstevel@tonic-gate   }
1071*7c478bd9Sstevel@tonic-gate   cleanup();
1072*7c478bd9Sstevel@tonic-gate }
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val)
1075*7c478bd9Sstevel@tonic-gate {
1076*7c478bd9Sstevel@tonic-gate   setup();
1077*7c478bd9Sstevel@tonic-gate   { begin_structure();
1078*7c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
1079*7c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1080*7c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
1081*7c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data);
1082*7c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,4,asn1_decode_int32);
1083*7c478bd9Sstevel@tonic-gate     end_structure();
1084*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
1085*7c478bd9Sstevel@tonic-gate   }
1086*7c478bd9Sstevel@tonic-gate   cleanup();
1087*7c478bd9Sstevel@tonic-gate }
1088*7c478bd9Sstevel@tonic-gate 
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val)
1091*7c478bd9Sstevel@tonic-gate {
1092*7c478bd9Sstevel@tonic-gate   setup();
1093*7c478bd9Sstevel@tonic-gate   { begin_structure();
1094*7c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
1095*7c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
1096*7c478bd9Sstevel@tonic-gate     get_field(val->stime,2,asn1_decode_kerberos_time);
1097*7c478bd9Sstevel@tonic-gate     get_field(val->susec,3,asn1_decode_int32);
1098*7c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
1099*7c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_realm);
1100*7c478bd9Sstevel@tonic-gate     get_field(val->client,5,asn1_decode_principal_name);
1101*7c478bd9Sstevel@tonic-gate     opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */
1102*7c478bd9Sstevel@tonic-gate     end_structure();
1103*7c478bd9Sstevel@tonic-gate     val->magic = KV5M_PREDICTED_SAM_RESPONSE;
1104*7c478bd9Sstevel@tonic-gate   }
1105*7c478bd9Sstevel@tonic-gate   cleanup();
1106*7c478bd9Sstevel@tonic-gate }
1107