1505d05c7Sgtb /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3505d05c7Sgtb  * Use is subject to license terms.
4505d05c7Sgtb  */
5505d05c7Sgtb 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * src/lib/krb5/asn.1/asn1_k_decode.c
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * Copyright 1994 by the Massachusetts Institute of Technology.
107c478bd9Sstevel@tonic-gate  * All Rights Reserved.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
137c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
147c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
157c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
257c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
267c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
277c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
287c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
297c478bd9Sstevel@tonic-gate  * or implied warranty.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "asn1_k_decode.h"
337c478bd9Sstevel@tonic-gate #include "asn1_decode.h"
347c478bd9Sstevel@tonic-gate #include "asn1_get.h"
357c478bd9Sstevel@tonic-gate #include "asn1_misc.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /* Declare useful decoder variables. */
387c478bd9Sstevel@tonic-gate #define setup()					\
397c478bd9Sstevel@tonic-gate   asn1_error_code retval;			\
407c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
417c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
427c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
437c478bd9Sstevel@tonic-gate   unsigned int length, taglen
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #define unused_var(x) if (0) { x = 0; x = x - x; }
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /* This is used for prefetch of next tag in sequence. */
487c478bd9Sstevel@tonic-gate #define next_tag()								\
497c478bd9Sstevel@tonic-gate { taginfo t2;									\
507c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(&subbuf, &t2);					\
517c478bd9Sstevel@tonic-gate   if (retval) return retval;							\
527c478bd9Sstevel@tonic-gate   /* Copy out to match previous functionality, until better integrated.  */	\
537c478bd9Sstevel@tonic-gate   asn1class = t2.asn1class;							\
547c478bd9Sstevel@tonic-gate   construction = t2.construction;						\
557c478bd9Sstevel@tonic-gate   tagnum = t2.tagnum;								\
567c478bd9Sstevel@tonic-gate   taglen = t2.length;								\
577c478bd9Sstevel@tonic-gate   indef = t2.indef;								\
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /* Force check for EOC tag. */
617c478bd9Sstevel@tonic-gate #define get_eoc()									\
627c478bd9Sstevel@tonic-gate     {											\
637c478bd9Sstevel@tonic-gate 	taginfo t3;									\
647c478bd9Sstevel@tonic-gate 	retval = asn1_get_tag_2(&subbuf, &t3);						\
657c478bd9Sstevel@tonic-gate 	if(retval) return retval;							\
667c478bd9Sstevel@tonic-gate         if (t3.asn1class != UNIVERSAL || t3.tagnum || t3.indef)				\
677c478bd9Sstevel@tonic-gate 	    return ASN1_MISSING_EOC;							\
687c478bd9Sstevel@tonic-gate         /* Copy out to match previous functionality, until better integrated.  */	\
697c478bd9Sstevel@tonic-gate 	asn1class = t3.asn1class;							\
707c478bd9Sstevel@tonic-gate 	construction = t3.construction;							\
717c478bd9Sstevel@tonic-gate 	tagnum = t3.tagnum;								\
727c478bd9Sstevel@tonic-gate 	taglen = t3.length;								\
737c478bd9Sstevel@tonic-gate 	indef = t3.indef;								\
747c478bd9Sstevel@tonic-gate     }
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #define alloc_field(var, type)			\
777c478bd9Sstevel@tonic-gate   var = (type*)calloc(1, sizeof(type));		\
787c478bd9Sstevel@tonic-gate   if ((var) == NULL) return ENOMEM
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* Fetch an expected APPLICATION class tag and verify. */
817c478bd9Sstevel@tonic-gate #define apptag(tagexpect)								\
827c478bd9Sstevel@tonic-gate   {											\
837c478bd9Sstevel@tonic-gate       taginfo t1;									\
847c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t1);						\
857c478bd9Sstevel@tonic-gate       if (retval) return retval;						   	\
867c478bd9Sstevel@tonic-gate       if (t1.asn1class != APPLICATION || t1.construction != CONSTRUCTED ||	   	\
877c478bd9Sstevel@tonic-gate 	  t1.tagnum != (tagexpect)) return ASN1_BAD_ID;					\
887c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */		\
897c478bd9Sstevel@tonic-gate       asn1class = t1.asn1class;								\
907c478bd9Sstevel@tonic-gate       construction = t1.construction;							\
917c478bd9Sstevel@tonic-gate       tagnum = t1.tagnum;								\
927c478bd9Sstevel@tonic-gate       applen = t1.length;								\
937c478bd9Sstevel@tonic-gate   }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /**** normal fields ****/
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * get_field_body
997c478bd9Sstevel@tonic-gate  *
1007c478bd9Sstevel@tonic-gate  * Get bare field.  This also prefetches the next tag.  The call to
1017c478bd9Sstevel@tonic-gate  * get_eoc() assumes that any values fetched by this macro are
1027c478bd9Sstevel@tonic-gate  * enclosed in a context-specific tag.
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate #define get_field_body(var, decoder)		\
1057c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(var));		\
1067c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
1077c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
1087c478bd9Sstevel@tonic-gate   next_tag()
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate  * get_field
1127c478bd9Sstevel@tonic-gate  *
1137c478bd9Sstevel@tonic-gate  * Get field having an expected context specific tag.  This assumes
1147c478bd9Sstevel@tonic-gate  * that context-specific tags are monotonically increasing in its
1157c478bd9Sstevel@tonic-gate  * verification of tag numbers.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate #define get_field(var, tagexpect, decoder)				\
1187c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
1197c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
1207c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1217c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
1227c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
1237c478bd9Sstevel@tonic-gate   get_field_body(var,decoder)
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * opt_field
1277c478bd9Sstevel@tonic-gate  *
1287c478bd9Sstevel@tonic-gate  * Get an optional field with an expected context specific tag.
1297c478bd9Sstevel@tonic-gate  * Assumes that OPTVAL will have the default value, thus failing to
1307c478bd9Sstevel@tonic-gate  * distinguish between absent optional values and present optional
1317c478bd9Sstevel@tonic-gate  * values that happen to have the value of OPTVAL.
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate #define opt_field(var, tagexpect, decoder, optvalue)			\
1347c478bd9Sstevel@tonic-gate   if (asn1buf_remains(&subbuf, seqindef)) {				\
1357c478bd9Sstevel@tonic-gate     if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1367c478bd9Sstevel@tonic-gate 	&& (tagnum || taglen || asn1class != UNIVERSAL))		\
1377c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;						\
1387c478bd9Sstevel@tonic-gate     if (tagnum == (tagexpect)) {					\
1397c478bd9Sstevel@tonic-gate       get_field_body(var, decoder);					\
1407c478bd9Sstevel@tonic-gate     } else var = optvalue;						\
1417c478bd9Sstevel@tonic-gate   }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate /**** fields w/ length ****/
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate /* similar to get_field_body */
1467c478bd9Sstevel@tonic-gate #define get_lenfield_body(len, var, decoder)	\
1477c478bd9Sstevel@tonic-gate   retval = decoder(&subbuf, &(len), &(var));	\
1487c478bd9Sstevel@tonic-gate   if (retval) return retval;			\
1497c478bd9Sstevel@tonic-gate   if (!taglen && indef) { get_eoc(); }		\
1507c478bd9Sstevel@tonic-gate   next_tag()
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /* similar to get_field_body */
1537c478bd9Sstevel@tonic-gate #define get_lenfield(len, var, tagexpect, decoder)			\
1547c478bd9Sstevel@tonic-gate   if (tagnum > (tagexpect)) return ASN1_MISSING_FIELD;			\
1557c478bd9Sstevel@tonic-gate   if (tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;		\
1567c478bd9Sstevel@tonic-gate   if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)	\
1577c478bd9Sstevel@tonic-gate       && (tagnum || taglen || asn1class != UNIVERSAL))			\
1587c478bd9Sstevel@tonic-gate     return ASN1_BAD_ID;							\
1597c478bd9Sstevel@tonic-gate   get_lenfield_body(len, var, decoder)
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate /* similar to opt_field */
1627c478bd9Sstevel@tonic-gate #define opt_lenfield(len, var, tagexpect, decoder)	\
1637c478bd9Sstevel@tonic-gate   if (tagnum == (tagexpect)) {				\
1647c478bd9Sstevel@tonic-gate     get_lenfield_body(len, var, decoder);		\
1657c478bd9Sstevel@tonic-gate   } else { len = 0; var = 0; }
1667c478bd9Sstevel@tonic-gate 
167*159d09a2SMark Phalan /*
168*159d09a2SMark Phalan  * Deal with implicitly tagged fields
169*159d09a2SMark Phalan  */
170*159d09a2SMark Phalan #define get_implicit_octet_string(len, var, tagexpect)		    \
171*159d09a2SMark Phalan   if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD;		    \
172*159d09a2SMark Phalan   if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE)   \
173*159d09a2SMark Phalan      return ASN1_BAD_ID;					    \
174*159d09a2SMark Phalan   retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));	    \
175*159d09a2SMark Phalan   if (retval) return retval;					    \
176*159d09a2SMark Phalan   (len) = taglen;						    \
177*159d09a2SMark Phalan   next_tag()
178*159d09a2SMark Phalan 
179*159d09a2SMark Phalan #define opt_implicit_octet_string(len, var, tagexpect)		    \
180*159d09a2SMark Phalan   if (tagnum == (tagexpect)) {					    \
181*159d09a2SMark Phalan     if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
182*159d09a2SMark Phalan 	return ASN1_BAD_ID;					    \
183*159d09a2SMark Phalan     retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var));   \
184*159d09a2SMark Phalan     if (retval) return retval;					    \
185*159d09a2SMark Phalan     (len) = taglen;						    \
186*159d09a2SMark Phalan     next_tag();							    \
187*159d09a2SMark Phalan   } else { (len) = 0; (var) = NULL; }
188*159d09a2SMark Phalan 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * begin_structure
1917c478bd9Sstevel@tonic-gate  *
1927c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE types.  This is meant
1937c478bd9Sstevel@tonic-gate  * to be called in an inner block that ends with a call to
1947c478bd9Sstevel@tonic-gate  * end_structure().
1957c478bd9Sstevel@tonic-gate  */
1967c478bd9Sstevel@tonic-gate #define begin_structure()					\
1977c478bd9Sstevel@tonic-gate   asn1buf subbuf;						\
1987c478bd9Sstevel@tonic-gate   int seqindef;							\
1997c478bd9Sstevel@tonic-gate   int indef;							\
2007c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqindef);		\
2017c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
2027c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
2037c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
2047c478bd9Sstevel@tonic-gate   next_tag()
2057c478bd9Sstevel@tonic-gate 
206*159d09a2SMark Phalan /*
207*159d09a2SMark Phalan  * This is used for structures which have no tagging.
208*159d09a2SMark Phalan  * It is the same as begin_structure() except next_tag()
209*159d09a2SMark Phalan  * is not called.
210*159d09a2SMark Phalan  */
211*159d09a2SMark Phalan #define begin_structure_no_tag()				\
212*159d09a2SMark Phalan   asn1buf subbuf;						\
213*159d09a2SMark Phalan   int seqindef;							\
214*159d09a2SMark Phalan   int indef;							\
215*159d09a2SMark Phalan   retval = asn1_get_sequence(buf, &length, &seqindef);		\
216*159d09a2SMark Phalan   if (retval) return retval;					\
217*159d09a2SMark Phalan   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
218*159d09a2SMark Phalan   if (retval) return retval
219*159d09a2SMark Phalan 
2207c478bd9Sstevel@tonic-gate /* skip trailing garbage */
2217c478bd9Sstevel@tonic-gate #define end_structure()						\
2227c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum,	\
2237c478bd9Sstevel@tonic-gate 			length, indef, seqindef);		\
2247c478bd9Sstevel@tonic-gate   if (retval) return retval
2257c478bd9Sstevel@tonic-gate 
226*159d09a2SMark Phalan /*
227*159d09a2SMark Phalan  * begin_choice
228*159d09a2SMark Phalan  *
229*159d09a2SMark Phalan  * Declares some variables for decoding CHOICE types.  This is meant
230*159d09a2SMark Phalan  * to be called in an inner block that ends with a call to
231*159d09a2SMark Phalan  * end_choice().
232*159d09a2SMark Phalan  */
233*159d09a2SMark Phalan #define begin_choice()						\
234*159d09a2SMark Phalan   asn1buf subbuf;						\
235*159d09a2SMark Phalan   int seqindef;							\
236*159d09a2SMark Phalan   int indef;							\
237*159d09a2SMark Phalan   taginfo t;							\
238*159d09a2SMark Phalan   retval = asn1_get_tag_2(buf, &t);				\
239*159d09a2SMark Phalan   if (retval) return retval;					\
240*159d09a2SMark Phalan   tagnum = t.tagnum;                                            \
241*159d09a2SMark Phalan   taglen = t.length;                                            \
242*159d09a2SMark Phalan   indef = t.indef;                                              \
243*159d09a2SMark Phalan   length = t.length;                                            \
244*159d09a2SMark Phalan   seqindef = t.indef;                                           \
245*159d09a2SMark Phalan   asn1class = t.asn1class;					\
246*159d09a2SMark Phalan   construction = t.construction;				\
247*159d09a2SMark Phalan   retval = asn1buf_imbed(&subbuf, buf, length, seqindef);	\
248*159d09a2SMark Phalan   if (retval) return retval
249*159d09a2SMark Phalan 
250*159d09a2SMark Phalan /* skip trailing garbage */
251*159d09a2SMark Phalan #define end_choice()						\
252*159d09a2SMark Phalan   length -= t.length;						\
253*159d09a2SMark Phalan   retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum,	\
254*159d09a2SMark Phalan 			length, t.indef, seqindef);		\
255*159d09a2SMark Phalan   if (retval) return retval
256*159d09a2SMark Phalan 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  * sequence_of
2597c478bd9Sstevel@tonic-gate  *
2607c478bd9Sstevel@tonic-gate  * Declares some variables for decoding SEQUENCE OF types.  This is
2617c478bd9Sstevel@tonic-gate  * meant to be called in an inner block that ends with a call to
2627c478bd9Sstevel@tonic-gate  * end_sequence_of().
2637c478bd9Sstevel@tonic-gate  */
2647c478bd9Sstevel@tonic-gate #define sequence_of(buf)			\
2657c478bd9Sstevel@tonic-gate   unsigned int length, taglen;			\
2667c478bd9Sstevel@tonic-gate   asn1_class asn1class;				\
2677c478bd9Sstevel@tonic-gate   asn1_construction construction;		\
2687c478bd9Sstevel@tonic-gate   asn1_tagnum tagnum;				\
2697c478bd9Sstevel@tonic-gate   int indef;					\
2707c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * sequence_of_no_tagvars
2747c478bd9Sstevel@tonic-gate  *
2757c478bd9Sstevel@tonic-gate  * This is meant for use inside decoder functions that have an outer
2767c478bd9Sstevel@tonic-gate  * sequence structure and thus declares variables of different names
2777c478bd9Sstevel@tonic-gate  * than does sequence_of() to avoid shadowing.
2787c478bd9Sstevel@tonic-gate  */
2797c478bd9Sstevel@tonic-gate #define sequence_of_no_tagvars(buf)		\
2807c478bd9Sstevel@tonic-gate   asn1_class eseqclass;				\
2817c478bd9Sstevel@tonic-gate   asn1_construction eseqconstr;			\
2827c478bd9Sstevel@tonic-gate   asn1_tagnum eseqnum;				\
2837c478bd9Sstevel@tonic-gate   unsigned int eseqlen;				\
2847c478bd9Sstevel@tonic-gate   int eseqindef;				\
2857c478bd9Sstevel@tonic-gate   sequence_of_common(buf)
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate  * sequence_of_common
2897c478bd9Sstevel@tonic-gate  *
2907c478bd9Sstevel@tonic-gate  * Fetches the outer SEQUENCE OF length info into {length,seqofindef}
2917c478bd9Sstevel@tonic-gate  * and imbeds an inner buffer seqbuf.  Unlike begin_structure(), it
2927c478bd9Sstevel@tonic-gate  * does not prefetch the next tag.
2937c478bd9Sstevel@tonic-gate  */
2947c478bd9Sstevel@tonic-gate #define sequence_of_common(buf)					\
2957c478bd9Sstevel@tonic-gate   int size = 0;							\
2967c478bd9Sstevel@tonic-gate   asn1buf seqbuf;						\
2977c478bd9Sstevel@tonic-gate   int seqofindef;						\
2987c478bd9Sstevel@tonic-gate   retval = asn1_get_sequence(buf, &length, &seqofindef);	\
2997c478bd9Sstevel@tonic-gate   if (retval) return retval;					\
3007c478bd9Sstevel@tonic-gate   retval = asn1buf_imbed(&seqbuf, buf, length, seqofindef);	\
3017c478bd9Sstevel@tonic-gate   if (retval) return retval
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate  * end_sequence_of
3057c478bd9Sstevel@tonic-gate  *
3067c478bd9Sstevel@tonic-gate  * Attempts to fetch an EOC tag, if any, and to sync over trailing
3077c478bd9Sstevel@tonic-gate  * garbage, if any.
3087c478bd9Sstevel@tonic-gate  */
3097c478bd9Sstevel@tonic-gate #define end_sequence_of(buf)							\
3107c478bd9Sstevel@tonic-gate   {										\
3117c478bd9Sstevel@tonic-gate       taginfo t4;								\
3127c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t4);					\
3137c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
3147c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
3157c478bd9Sstevel@tonic-gate       asn1class = t4.asn1class;							\
3167c478bd9Sstevel@tonic-gate       construction = t4.construction;						\
3177c478bd9Sstevel@tonic-gate       tagnum = t4.tagnum;							\
3187c478bd9Sstevel@tonic-gate       taglen = t4.length;							\
3197c478bd9Sstevel@tonic-gate       indef = t4.indef;								\
3207c478bd9Sstevel@tonic-gate   }										\
3217c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, asn1class, tagnum,			\
3227c478bd9Sstevel@tonic-gate 			length, indef, seqofindef);				\
3237c478bd9Sstevel@tonic-gate   if (retval) return retval;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate  * end_sequence_of_no_tagvars
3277c478bd9Sstevel@tonic-gate  *
3287c478bd9Sstevel@tonic-gate  * Like end_sequence_of(), but uses the different (non-shadowing)
3297c478bd9Sstevel@tonic-gate  * variable names.
3307c478bd9Sstevel@tonic-gate  */
3317c478bd9Sstevel@tonic-gate #define end_sequence_of_no_tagvars(buf)						\
3327c478bd9Sstevel@tonic-gate   {										\
3337c478bd9Sstevel@tonic-gate       taginfo t5;								\
3347c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(&seqbuf, &t5);					\
3357c478bd9Sstevel@tonic-gate       if (retval) return retval;						\
3367c478bd9Sstevel@tonic-gate       /* Copy out to match previous functionality, until better integrated.  */	\
3377c478bd9Sstevel@tonic-gate       eseqclass = t5.asn1class;							\
3387c478bd9Sstevel@tonic-gate       eseqconstr = t5.construction;						\
3397c478bd9Sstevel@tonic-gate       eseqnum = t5.tagnum;							\
3407c478bd9Sstevel@tonic-gate       eseqlen = t5.length;							\
3417c478bd9Sstevel@tonic-gate       eseqindef = t5.indef;							\
3427c478bd9Sstevel@tonic-gate   }										\
3437c478bd9Sstevel@tonic-gate   retval = asn1buf_sync(buf, &seqbuf, eseqclass, eseqnum,			\
3447c478bd9Sstevel@tonic-gate 			eseqlen, eseqindef, seqofindef);			\
3457c478bd9Sstevel@tonic-gate   if (retval) return retval;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate #define cleanup()				\
3487c478bd9Sstevel@tonic-gate   return 0
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /* scalars */
3517c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kerberos_time(asn1buf *buf, krb5_timestamp *val)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate     time_t	t;
3547c478bd9Sstevel@tonic-gate     asn1_error_code retval;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate     retval =  asn1_decode_generaltime(buf,&t);
3577c478bd9Sstevel@tonic-gate     if (retval)
3587c478bd9Sstevel@tonic-gate 	return retval;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate     *val = t;
3617c478bd9Sstevel@tonic-gate     return 0;
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate #define integer_convert(fname,ktype)\
3657c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
3667c478bd9Sstevel@tonic-gate {\
3677c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
3687c478bd9Sstevel@tonic-gate   long n;\
3697c478bd9Sstevel@tonic-gate   retval = asn1_decode_integer(buf,&n);\
3707c478bd9Sstevel@tonic-gate   if(retval) return retval;\
3717c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
3727c478bd9Sstevel@tonic-gate   return 0;\
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate #define unsigned_integer_convert(fname,ktype)\
3757c478bd9Sstevel@tonic-gate asn1_error_code fname(asn1buf * buf, ktype * val)\
3767c478bd9Sstevel@tonic-gate {\
3777c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
3787c478bd9Sstevel@tonic-gate   unsigned long n;\
3797c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);\
3807c478bd9Sstevel@tonic-gate   if(retval) return retval;\
3817c478bd9Sstevel@tonic-gate   *val = (ktype)n;\
3827c478bd9Sstevel@tonic-gate   return 0;\
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int,int)
3857c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_int32,krb5_int32)
3867c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_kvno,krb5_kvno)
3877c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_enctype,krb5_enctype)
3887c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
3897c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_octet,krb5_octet)
3907c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_addrtype,krb5_addrtype)
3917c478bd9Sstevel@tonic-gate integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
3927c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
3937c478bd9Sstevel@tonic-gate unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate   asn1_error_code retval;
3987c478bd9Sstevel@tonic-gate   unsigned long n;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate   retval = asn1_decode_maybe_unsigned(buf, &n);
4017c478bd9Sstevel@tonic-gate   if (retval) return retval;
4027c478bd9Sstevel@tonic-gate   *val = (krb5_ui_4)n & 0xffffffff;
4037c478bd9Sstevel@tonic-gate   return 0;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate   asn1_error_code retval;
4097c478bd9Sstevel@tonic-gate   unsigned long n;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate   retval = asn1_decode_unsigned_integer(buf,&n);
4127c478bd9Sstevel@tonic-gate   if(retval) return retval;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate   *val = (krb5_msgtype) n;
4157c478bd9Sstevel@tonic-gate   return 0;
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate /* structures */
4207c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_realm(asn1buf *buf, krb5_principal *val)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate   return asn1_decode_generalstring(buf,
423505d05c7Sgtb 				   &((*val)->realm.length),
4247c478bd9Sstevel@tonic-gate 				   &((*val)->realm.data));
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate   setup();
4307c478bd9Sstevel@tonic-gate   { begin_structure();
4317c478bd9Sstevel@tonic-gate     get_field((*val)->type,0,asn1_decode_int32);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
4347c478bd9Sstevel@tonic-gate       while(asn1buf_remains(&seqbuf,seqofindef) > 0){
4357c478bd9Sstevel@tonic-gate 	size++;
4367c478bd9Sstevel@tonic-gate 	if ((*val)->data == NULL)
4377c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
4387c478bd9Sstevel@tonic-gate 	else
4397c478bd9Sstevel@tonic-gate 	  (*val)->data = (krb5_data*)realloc((*val)->data,
4407c478bd9Sstevel@tonic-gate 					     size*sizeof(krb5_data));
4417c478bd9Sstevel@tonic-gate 	if((*val)->data == NULL) return ENOMEM;
4427c478bd9Sstevel@tonic-gate 	retval = asn1_decode_generalstring(&seqbuf,
443505d05c7Sgtb 					   &((*val)->data[size-1].length),
444*159d09a2SMark Phalan 					   &((*val)->data[size-1].data));
4457c478bd9Sstevel@tonic-gate 	if(retval) return retval;
4467c478bd9Sstevel@tonic-gate       }
4477c478bd9Sstevel@tonic-gate       (*val)->length = size;
4487c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
4497c478bd9Sstevel@tonic-gate     }
4507c478bd9Sstevel@tonic-gate     if (indef) {
4517c478bd9Sstevel@tonic-gate 	get_eoc();
4527c478bd9Sstevel@tonic-gate     }
4537c478bd9Sstevel@tonic-gate     next_tag();
4547c478bd9Sstevel@tonic-gate     end_structure();
4557c478bd9Sstevel@tonic-gate     (*val)->magic = KV5M_PRINCIPAL;
4567c478bd9Sstevel@tonic-gate   }
4577c478bd9Sstevel@tonic-gate   cleanup();
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_checksum(asn1buf *buf, krb5_checksum *val)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate   setup();
4637c478bd9Sstevel@tonic-gate   { begin_structure();
4647c478bd9Sstevel@tonic-gate     get_field(val->checksum_type,0,asn1_decode_cksumtype);
4657c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
4667c478bd9Sstevel@tonic-gate     end_structure();
4677c478bd9Sstevel@tonic-gate     val->magic = KV5M_CHECKSUM;
4687c478bd9Sstevel@tonic-gate   }
4697c478bd9Sstevel@tonic-gate   cleanup();
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encryption_key(asn1buf *buf, krb5_keyblock *val)
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate   setup();
4757c478bd9Sstevel@tonic-gate   { begin_structure();
4767c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
4777c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
4787c478bd9Sstevel@tonic-gate     end_structure();
4797c478bd9Sstevel@tonic-gate     val->magic = KV5M_KEYBLOCK;
4807c478bd9Sstevel@tonic-gate   }
4817c478bd9Sstevel@tonic-gate   cleanup();
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_encrypted_data(asn1buf *buf, krb5_enc_data *val)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate   setup();
4877c478bd9Sstevel@tonic-gate   { begin_structure();
4887c478bd9Sstevel@tonic-gate     get_field(val->enctype,0,asn1_decode_enctype);
4897c478bd9Sstevel@tonic-gate     opt_field(val->kvno,1,asn1_decode_kvno,0);
4907c478bd9Sstevel@tonic-gate     get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
4917c478bd9Sstevel@tonic-gate     end_structure();
4927c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_DATA;
4937c478bd9Sstevel@tonic-gate   }
4947c478bd9Sstevel@tonic-gate   cleanup();
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb5_flags(asn1buf *buf, krb5_flags *val)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate   asn1_error_code retval;
5007c478bd9Sstevel@tonic-gate   asn1_octet unused, o;
5017c478bd9Sstevel@tonic-gate   taginfo t;
5027c478bd9Sstevel@tonic-gate   int i;
5037c478bd9Sstevel@tonic-gate   krb5_flags f=0;
5047c478bd9Sstevel@tonic-gate   unsigned int length;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate   retval = asn1_get_tag_2(buf, &t);
5077c478bd9Sstevel@tonic-gate   if (retval) return retval;
5087c478bd9Sstevel@tonic-gate   if (t.asn1class != UNIVERSAL || t.construction != PRIMITIVE ||
5097c478bd9Sstevel@tonic-gate       t.tagnum != ASN1_BITSTRING)
5107c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
5117c478bd9Sstevel@tonic-gate   length = t.length;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate   retval = asn1buf_remove_octet(buf,&unused); /* # of padding bits */
5147c478bd9Sstevel@tonic-gate   if(retval) return retval;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate   /* Number of unused bits must be between 0 and 7. */
5177c478bd9Sstevel@tonic-gate   if (unused > 7) return ASN1_BAD_FORMAT;
5187c478bd9Sstevel@tonic-gate   length--;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate   for(i = 0; i < length; i++) {
5217c478bd9Sstevel@tonic-gate     retval = asn1buf_remove_octet(buf,&o);
5227c478bd9Sstevel@tonic-gate     if(retval) return retval;
5237c478bd9Sstevel@tonic-gate     /* ignore bits past number 31 */
5247c478bd9Sstevel@tonic-gate     if (i < 4)
5257c478bd9Sstevel@tonic-gate       f = (f<<8) | ((krb5_flags)o&0xFF);
5267c478bd9Sstevel@tonic-gate   }
5277c478bd9Sstevel@tonic-gate   if (length <= 4) {
5287c478bd9Sstevel@tonic-gate     /* Mask out unused bits, but only if necessary. */
5297c478bd9Sstevel@tonic-gate     f &= ~(krb5_flags)0 << unused;
5307c478bd9Sstevel@tonic-gate   }
5317c478bd9Sstevel@tonic-gate   /* left-justify */
5327c478bd9Sstevel@tonic-gate   if (length < 4)
5337c478bd9Sstevel@tonic-gate     f <<= (4 - length) * 8;
5347c478bd9Sstevel@tonic-gate   *val = f;
5357c478bd9Sstevel@tonic-gate   return 0;
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket_flags(asn1buf *buf, krb5_flags *val)
5397c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ap_options(asn1buf *buf, krb5_flags *val)
5427c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_options(asn1buf *buf, krb5_flags *val)
5457c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_transited_encoding(asn1buf *buf, krb5_transited *val)
5487c478bd9Sstevel@tonic-gate {
5497c478bd9Sstevel@tonic-gate   setup();
5507c478bd9Sstevel@tonic-gate   { begin_structure();
5517c478bd9Sstevel@tonic-gate     get_field(val->tr_type,0,asn1_decode_octet);
5527c478bd9Sstevel@tonic-gate     get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
5537c478bd9Sstevel@tonic-gate     end_structure();
5547c478bd9Sstevel@tonic-gate     val->magic = KV5M_TRANSITED;
5557c478bd9Sstevel@tonic-gate   }
5567c478bd9Sstevel@tonic-gate   cleanup();
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_kdc_rep_part(asn1buf *buf, krb5_enc_kdc_rep_part *val)
5607c478bd9Sstevel@tonic-gate {
5617c478bd9Sstevel@tonic-gate   setup();
5627c478bd9Sstevel@tonic-gate   { begin_structure();
5637c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
5647c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
5657c478bd9Sstevel@tonic-gate     get_field(val->last_req,1,asn1_decode_last_req);
5667c478bd9Sstevel@tonic-gate     get_field(val->nonce,2,asn1_decode_int32);
5677c478bd9Sstevel@tonic-gate     opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
5687c478bd9Sstevel@tonic-gate     get_field(val->flags,4,asn1_decode_ticket_flags);
5697c478bd9Sstevel@tonic-gate     get_field(val->times.authtime,5,asn1_decode_kerberos_time);
5707c478bd9Sstevel@tonic-gate     /* Set to authtime if missing */
5717c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,6,asn1_decode_kerberos_time,val->times.authtime);
5727c478bd9Sstevel@tonic-gate     get_field(val->times.endtime,7,asn1_decode_kerberos_time);
5737c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
5747c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5757c478bd9Sstevel@tonic-gate     get_field(val->server,9,asn1_decode_realm);
5767c478bd9Sstevel@tonic-gate     get_field(val->server,10,asn1_decode_principal_name);
5777c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
5787c478bd9Sstevel@tonic-gate     end_structure();
5797c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_KDC_REP_PART;
5807c478bd9Sstevel@tonic-gate   }
5817c478bd9Sstevel@tonic-gate   cleanup();
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate   setup();
5877c478bd9Sstevel@tonic-gate   unsigned int applen;
5887c478bd9Sstevel@tonic-gate   apptag(1);
5897c478bd9Sstevel@tonic-gate   { begin_structure();
5907c478bd9Sstevel@tonic-gate     { krb5_kvno vno;
5917c478bd9Sstevel@tonic-gate       get_field(vno,0,asn1_decode_kvno);
5927c478bd9Sstevel@tonic-gate       if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
5937c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
5947c478bd9Sstevel@tonic-gate     get_field(val->server,1,asn1_decode_realm);
5957c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_principal_name);
5967c478bd9Sstevel@tonic-gate     get_field(val->enc_part,3,asn1_decode_encrypted_data);
5977c478bd9Sstevel@tonic-gate     end_structure();
5987c478bd9Sstevel@tonic-gate     val->magic = KV5M_TICKET;
5997c478bd9Sstevel@tonic-gate   }
6007c478bd9Sstevel@tonic-gate   if (!applen) {
6017c478bd9Sstevel@tonic-gate       taginfo t;
6027c478bd9Sstevel@tonic-gate       retval = asn1_get_tag_2(buf, &t);
603505d05c7Sgtb       if (retval) return retval;
604*159d09a2SMark Phalan   }
6057c478bd9Sstevel@tonic-gate   cleanup();
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req(asn1buf *buf, krb5_kdc_req *val)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate   setup();
6117c478bd9Sstevel@tonic-gate   { begin_structure();
6127c478bd9Sstevel@tonic-gate     { krb5_kvno kvno;
6137c478bd9Sstevel@tonic-gate       get_field(kvno,1,asn1_decode_kvno);
6147c478bd9Sstevel@tonic-gate       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
6157c478bd9Sstevel@tonic-gate     get_field(val->msg_type,2,asn1_decode_msgtype);
6167c478bd9Sstevel@tonic-gate     opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
6177c478bd9Sstevel@tonic-gate     get_field(*val,4,asn1_decode_kdc_req_body);
6187c478bd9Sstevel@tonic-gate     end_structure();
6197c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
6207c478bd9Sstevel@tonic-gate   }
6217c478bd9Sstevel@tonic-gate   cleanup();
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_req_body(asn1buf *buf, krb5_kdc_req *val)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate   setup();
6277c478bd9Sstevel@tonic-gate   {
6287c478bd9Sstevel@tonic-gate     krb5_principal psave;
6297c478bd9Sstevel@tonic-gate     begin_structure();
6307c478bd9Sstevel@tonic-gate     get_field(val->kdc_options,0,asn1_decode_kdc_options);
6317c478bd9Sstevel@tonic-gate     if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
6327c478bd9Sstevel@tonic-gate     opt_field(val->client,1,asn1_decode_principal_name,NULL);
6337c478bd9Sstevel@tonic-gate     alloc_field(val->server,krb5_principal_data);
6347c478bd9Sstevel@tonic-gate     get_field(val->server,2,asn1_decode_realm);
6357c478bd9Sstevel@tonic-gate     if(val->client != NULL){
6367c478bd9Sstevel@tonic-gate       retval = asn1_krb5_realm_copy(val->client,val->server);
637505d05c7Sgtb       if(retval) return retval; }
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate     /* If opt_field server is missing, memory reference to server is
6407c478bd9Sstevel@tonic-gate        lost and results in memory leak */
6417c478bd9Sstevel@tonic-gate     psave = val->server;
6427c478bd9Sstevel@tonic-gate     opt_field(val->server,3,asn1_decode_principal_name,NULL);
6437c478bd9Sstevel@tonic-gate     if(val->server == NULL){
6447c478bd9Sstevel@tonic-gate       if(psave->realm.data) {
6457c478bd9Sstevel@tonic-gate 	free(psave->realm.data);
6467c478bd9Sstevel@tonic-gate 	psave->realm.data = NULL;
6477c478bd9Sstevel@tonic-gate 	psave->realm.length=0;
6487c478bd9Sstevel@tonic-gate       }
6497c478bd9Sstevel@tonic-gate       free(psave);
6507c478bd9Sstevel@tonic-gate     }
6517c478bd9Sstevel@tonic-gate     opt_field(val->from,4,asn1_decode_kerberos_time,0);
6527c478bd9Sstevel@tonic-gate     get_field(val->till,5,asn1_decode_kerberos_time);
6537c478bd9Sstevel@tonic-gate     opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
6547c478bd9Sstevel@tonic-gate     get_field(val->nonce,7,asn1_decode_int32);
6557c478bd9Sstevel@tonic-gate     get_lenfield(val->nktypes,val->ktype,8,asn1_decode_sequence_of_enctype);
6567c478bd9Sstevel@tonic-gate     opt_field(val->addresses,9,asn1_decode_host_addresses,0);
6577c478bd9Sstevel@tonic-gate     if(tagnum == 10){
6587c478bd9Sstevel@tonic-gate       get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
6597c478bd9Sstevel@tonic-gate     else{
6607c478bd9Sstevel@tonic-gate       val->authorization_data.magic = KV5M_ENC_DATA;
6617c478bd9Sstevel@tonic-gate       val->authorization_data.enctype = 0;
6627c478bd9Sstevel@tonic-gate       val->authorization_data.kvno = 0;
6637c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.data = NULL;
6647c478bd9Sstevel@tonic-gate       val->authorization_data.ciphertext.length = 0;
6657c478bd9Sstevel@tonic-gate     }
6667c478bd9Sstevel@tonic-gate     opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
6677c478bd9Sstevel@tonic-gate     end_structure();
6687c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REQ;
6697c478bd9Sstevel@tonic-gate   }
6707c478bd9Sstevel@tonic-gate   cleanup();
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_safe_body(asn1buf *buf, krb5_safe *val)
6747c478bd9Sstevel@tonic-gate {
6757c478bd9Sstevel@tonic-gate   setup();
6767c478bd9Sstevel@tonic-gate   { begin_structure();
6777c478bd9Sstevel@tonic-gate     get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
6787c478bd9Sstevel@tonic-gate     opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
6797c478bd9Sstevel@tonic-gate     opt_field(val->usec,2,asn1_decode_int32,0);
6807c478bd9Sstevel@tonic-gate     opt_field(val->seq_number,3,asn1_decode_seqnum,0);
6817c478bd9Sstevel@tonic-gate     alloc_field(val->s_address,krb5_address);
6827c478bd9Sstevel@tonic-gate     get_field(*(val->s_address),4,asn1_decode_host_address);
6837c478bd9Sstevel@tonic-gate     if(tagnum == 5){
6847c478bd9Sstevel@tonic-gate       alloc_field(val->r_address,krb5_address);
6857c478bd9Sstevel@tonic-gate       get_field(*(val->r_address),5,asn1_decode_host_address);
6867c478bd9Sstevel@tonic-gate     } else val->r_address = NULL;
6877c478bd9Sstevel@tonic-gate     end_structure();
6887c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAFE;
6897c478bd9Sstevel@tonic-gate   }
6907c478bd9Sstevel@tonic-gate   cleanup();
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_address(asn1buf *buf, krb5_address *val)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate   setup();
6967c478bd9Sstevel@tonic-gate   { begin_structure();
6977c478bd9Sstevel@tonic-gate     get_field(val->addrtype,0,asn1_decode_addrtype);
6987c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
6997c478bd9Sstevel@tonic-gate     end_structure();
7007c478bd9Sstevel@tonic-gate     val->magic = KV5M_ADDRESS;
7017c478bd9Sstevel@tonic-gate   }
7027c478bd9Sstevel@tonic-gate   cleanup();
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_kdc_rep(asn1buf *buf, krb5_kdc_rep *val)
7067c478bd9Sstevel@tonic-gate {
7077c478bd9Sstevel@tonic-gate   setup();
7087c478bd9Sstevel@tonic-gate   { begin_structure();
7097c478bd9Sstevel@tonic-gate     { krb5_kvno pvno;
7107c478bd9Sstevel@tonic-gate       get_field(pvno,0,asn1_decode_kvno);
7117c478bd9Sstevel@tonic-gate       if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
7127c478bd9Sstevel@tonic-gate     get_field(val->msg_type,1,asn1_decode_msgtype);
7137c478bd9Sstevel@tonic-gate     opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
7147c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
7157c478bd9Sstevel@tonic-gate     get_field(val->client,3,asn1_decode_realm);
7167c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_principal_name);
7177c478bd9Sstevel@tonic-gate     alloc_field(val->ticket,krb5_ticket);
7187c478bd9Sstevel@tonic-gate     get_field(*(val->ticket),5,asn1_decode_ticket);
7197c478bd9Sstevel@tonic-gate     get_field(val->enc_part,6,asn1_decode_encrypted_data);
7207c478bd9Sstevel@tonic-gate     end_structure();
7217c478bd9Sstevel@tonic-gate     val->magic = KV5M_KDC_REP;
7227c478bd9Sstevel@tonic-gate   }
7237c478bd9Sstevel@tonic-gate   cleanup();
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate /* arrays */
7287c478bd9Sstevel@tonic-gate #define get_element(element,decoder)\
7297c478bd9Sstevel@tonic-gate retval = decoder(&seqbuf,element);\
7307c478bd9Sstevel@tonic-gate if(retval) return retval
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate #define array_append(array,size,element,type)\
7337c478bd9Sstevel@tonic-gate size++;\
7347c478bd9Sstevel@tonic-gate if (*(array) == NULL)\
7357c478bd9Sstevel@tonic-gate      *(array) = (type**)malloc((size+1)*sizeof(type*));\
7367c478bd9Sstevel@tonic-gate else\
7377c478bd9Sstevel@tonic-gate   *(array) = (type**)realloc(*(array),\
7387c478bd9Sstevel@tonic-gate 			     (size+1)*sizeof(type*));\
7397c478bd9Sstevel@tonic-gate if(*(array) == NULL) return ENOMEM;\
7407c478bd9Sstevel@tonic-gate (*(array))[(size)-1] = elt
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate #define decode_array_body(type,decoder)\
7437c478bd9Sstevel@tonic-gate   asn1_error_code retval;\
7447c478bd9Sstevel@tonic-gate   type *elt;\
7457c478bd9Sstevel@tonic-gate \
7467c478bd9Sstevel@tonic-gate   { sequence_of(buf);\
7477c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){\
7487c478bd9Sstevel@tonic-gate       alloc_field(elt,type);\
7497c478bd9Sstevel@tonic-gate       get_element(elt,decoder);\
7507c478bd9Sstevel@tonic-gate       array_append(val,size,elt,type);\
7517c478bd9Sstevel@tonic-gate     }\
7527c478bd9Sstevel@tonic-gate     if (*val == NULL)\
7537c478bd9Sstevel@tonic-gate 	*val = (type **)malloc(sizeof(type*));\
7547c478bd9Sstevel@tonic-gate     (*val)[size] = NULL;\
7557c478bd9Sstevel@tonic-gate     end_sequence_of(buf);\
7567c478bd9Sstevel@tonic-gate   }\
7577c478bd9Sstevel@tonic-gate   cleanup()
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authorization_data(asn1buf *buf, krb5_authdata ***val)
7617c478bd9Sstevel@tonic-gate {
7627c478bd9Sstevel@tonic-gate   decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate   setup();
7687c478bd9Sstevel@tonic-gate   { begin_structure();
7697c478bd9Sstevel@tonic-gate     get_field(val->ad_type,0,asn1_decode_authdatatype);
7707c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
7717c478bd9Sstevel@tonic-gate     end_structure();
7727c478bd9Sstevel@tonic-gate     val->magic = KV5M_AUTHDATA;
7737c478bd9Sstevel@tonic-gate   }
7747c478bd9Sstevel@tonic-gate   cleanup();
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_host_addresses(asn1buf *buf, krb5_address ***val)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate   decode_array_body(krb5_address,asn1_decode_host_address);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_ticket(asn1buf *buf, krb5_ticket ***val)
7837c478bd9Sstevel@tonic-gate {
7847c478bd9Sstevel@tonic-gate   decode_array_body(krb5_ticket,asn1_decode_ticket);
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_krb_cred_info(asn1buf *buf, krb5_cred_info ***val)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate   decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val)
7937c478bd9Sstevel@tonic-gate {
7947c478bd9Sstevel@tonic-gate   setup();
7957c478bd9Sstevel@tonic-gate   { begin_structure();
7967c478bd9Sstevel@tonic-gate     alloc_field(val->session,krb5_keyblock);
7977c478bd9Sstevel@tonic-gate     get_field(*(val->session),0,asn1_decode_encryption_key);
7987c478bd9Sstevel@tonic-gate     if(tagnum == 1){
7997c478bd9Sstevel@tonic-gate       alloc_field(val->client,krb5_principal_data);
8007c478bd9Sstevel@tonic-gate       opt_field(val->client,1,asn1_decode_realm,NULL);
8017c478bd9Sstevel@tonic-gate       opt_field(val->client,2,asn1_decode_principal_name,NULL); }
8027c478bd9Sstevel@tonic-gate     opt_field(val->flags,3,asn1_decode_ticket_flags,0);
8037c478bd9Sstevel@tonic-gate     opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
8047c478bd9Sstevel@tonic-gate     opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
8057c478bd9Sstevel@tonic-gate     opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
8067c478bd9Sstevel@tonic-gate     opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
8077c478bd9Sstevel@tonic-gate     if(tagnum == 8){
8087c478bd9Sstevel@tonic-gate       alloc_field(val->server,krb5_principal_data);
8097c478bd9Sstevel@tonic-gate       opt_field(val->server,8,asn1_decode_realm,NULL);
8107c478bd9Sstevel@tonic-gate       opt_field(val->server,9,asn1_decode_principal_name,NULL); }
8117c478bd9Sstevel@tonic-gate     opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
8127c478bd9Sstevel@tonic-gate     end_structure();
8137c478bd9Sstevel@tonic-gate     val->magic = KV5M_CRED_INFO;
8147c478bd9Sstevel@tonic-gate   }
8157c478bd9Sstevel@tonic-gate   cleanup();
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_pa_data(asn1buf *buf, krb5_pa_data ***val)
8197c478bd9Sstevel@tonic-gate {
8207c478bd9Sstevel@tonic-gate   decode_array_body(krb5_pa_data,asn1_decode_pa_data);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_pa_data(asn1buf *buf, krb5_pa_data *val)
8247c478bd9Sstevel@tonic-gate {
8257c478bd9Sstevel@tonic-gate   setup();
8267c478bd9Sstevel@tonic-gate   { begin_structure();
8277c478bd9Sstevel@tonic-gate     get_field(val->pa_type,1,asn1_decode_int32);
8287c478bd9Sstevel@tonic-gate     get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
8297c478bd9Sstevel@tonic-gate     end_structure();
8307c478bd9Sstevel@tonic-gate     val->magic = KV5M_PA_DATA;
8317c478bd9Sstevel@tonic-gate   }
8327c478bd9Sstevel@tonic-gate   cleanup();
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req(asn1buf *buf, krb5_last_req_entry ***val)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate   decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_last_req_entry(asn1buf *buf, krb5_last_req_entry *val)
8417c478bd9Sstevel@tonic-gate {
8427c478bd9Sstevel@tonic-gate   setup();
8437c478bd9Sstevel@tonic-gate   { begin_structure();
8447c478bd9Sstevel@tonic-gate     get_field(val->lr_type,0,asn1_decode_int32);
8457c478bd9Sstevel@tonic-gate     get_field(val->value,1,asn1_decode_kerberos_time);
8467c478bd9Sstevel@tonic-gate     end_structure();
8477c478bd9Sstevel@tonic-gate     val->magic = KV5M_LAST_REQ_ENTRY;
8487c478bd9Sstevel@tonic-gate #ifdef KRB5_GENEROUS_LR_TYPE
8497c478bd9Sstevel@tonic-gate     /* If we are only a single byte wide and negative - fill in the
8507c478bd9Sstevel@tonic-gate        other bits */
8517c478bd9Sstevel@tonic-gate     if((val->lr_type & 0xffffff80U) == 0x80) val->lr_type |= 0xffffff00U;
8527c478bd9Sstevel@tonic-gate #endif
8537c478bd9Sstevel@tonic-gate   }
8547c478bd9Sstevel@tonic-gate   cleanup();
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_enctype(asn1buf *buf, int *num, krb5_enctype **val)
8587c478bd9Sstevel@tonic-gate {
8597c478bd9Sstevel@tonic-gate   asn1_error_code retval;
8607c478bd9Sstevel@tonic-gate   { sequence_of(buf);
8617c478bd9Sstevel@tonic-gate     while(asn1buf_remains(&seqbuf,seqofindef) > 0){
8627c478bd9Sstevel@tonic-gate       size++;
8637c478bd9Sstevel@tonic-gate       if (*val == NULL)
8647c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
8657c478bd9Sstevel@tonic-gate       else
8667c478bd9Sstevel@tonic-gate         *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
8677c478bd9Sstevel@tonic-gate       if(*val == NULL) return ENOMEM;
8687c478bd9Sstevel@tonic-gate       retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
8697c478bd9Sstevel@tonic-gate       if(retval) return retval;
8707c478bd9Sstevel@tonic-gate     }
8717c478bd9Sstevel@tonic-gate     *num = size;
8727c478bd9Sstevel@tonic-gate     end_sequence_of(buf);
8737c478bd9Sstevel@tonic-gate   }
8747c478bd9Sstevel@tonic-gate   cleanup();
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_checksum(asn1buf *buf, krb5_checksum ***val)
8787c478bd9Sstevel@tonic-gate {
8797c478bd9Sstevel@tonic-gate   decode_array_body(krb5_checksum, asn1_decode_checksum);
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry(asn1buf *buf, krb5_etype_info_entry *val )
8837c478bd9Sstevel@tonic-gate {
88486aa8097Smp   /*
88586aa8097Smp    * Solaris Kerberos:
88686aa8097Smp    * Use a temporary char* (tmpp) in place of val->salt when calling
88786aa8097Smp    * get_lenfield(). val->salt cannot be cast to a char* as casting will not
88886aa8097Smp    * produce an lvalue. Use the new value pointed to by tmpp as the value for
88986aa8097Smp    * val->salt.
89086aa8097Smp    */
891505d05c7Sgtb   char *tmpp;
8927c478bd9Sstevel@tonic-gate   setup();
8937c478bd9Sstevel@tonic-gate   { begin_structure();
8947c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
8957c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
896505d05c7Sgtb       get_lenfield(val->length,tmpp,1,asn1_decode_generalstring);
89786aa8097Smp       val->salt = (krb5_octet*)tmpp;	/* SUNW14resync hack */
8987c478bd9Sstevel@tonic-gate     } else {
8997c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
9007c478bd9Sstevel@tonic-gate 	    val->salt = 0;
9017c478bd9Sstevel@tonic-gate     }
9027c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
9037c478bd9Sstevel@tonic-gate       krb5_octet *params ;
9047c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
9057c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
9067c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
9077c478bd9Sstevel@tonic-gate     } else {
9087c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
9097c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
9107c478bd9Sstevel@tonic-gate     }
9117c478bd9Sstevel@tonic-gate     end_structure();
9127c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
9137c478bd9Sstevel@tonic-gate   }
9147c478bd9Sstevel@tonic-gate   cleanup();
9157c478bd9Sstevel@tonic-gate }
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate static asn1_error_code asn1_decode_etype_info2_entry_1_3(asn1buf *buf, krb5_etype_info_entry *val )
9187c478bd9Sstevel@tonic-gate {
9197c478bd9Sstevel@tonic-gate   setup();
9207c478bd9Sstevel@tonic-gate   { begin_structure();
9217c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
9227c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
9237c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
9247c478bd9Sstevel@tonic-gate     } else {
9257c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
9267c478bd9Sstevel@tonic-gate 	    val->salt = 0;
9277c478bd9Sstevel@tonic-gate     }
9287c478bd9Sstevel@tonic-gate     if ( tagnum ==2) {
9297c478bd9Sstevel@tonic-gate       krb5_octet *params ;
9307c478bd9Sstevel@tonic-gate       get_lenfield( val->s2kparams.length, params,
9317c478bd9Sstevel@tonic-gate 		      2, asn1_decode_octetstring);
9327c478bd9Sstevel@tonic-gate       val->s2kparams.data = ( char *) params;
9337c478bd9Sstevel@tonic-gate     } else {
9347c478bd9Sstevel@tonic-gate 	val->s2kparams.data = NULL;
9357c478bd9Sstevel@tonic-gate 	val->s2kparams.length = 0;
9367c478bd9Sstevel@tonic-gate     }
9377c478bd9Sstevel@tonic-gate     end_structure();
9387c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
9397c478bd9Sstevel@tonic-gate   }
9407c478bd9Sstevel@tonic-gate   cleanup();
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate 
943505d05c7Sgtb 
944505d05c7Sgtb static asn1_error_code asn1_decode_etype_info_entry(asn1buf *buf, krb5_etype_info_entry *val )
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate   setup();
9477c478bd9Sstevel@tonic-gate   { begin_structure();
9487c478bd9Sstevel@tonic-gate     get_field(val->etype,0,asn1_decode_enctype);
9497c478bd9Sstevel@tonic-gate     if (tagnum == 1) {
9507c478bd9Sstevel@tonic-gate 	    get_lenfield(val->length,val->salt,1,asn1_decode_octetstring);
9517c478bd9Sstevel@tonic-gate     } else {
9527c478bd9Sstevel@tonic-gate 	    val->length = KRB5_ETYPE_NO_SALT;
9537c478bd9Sstevel@tonic-gate 	    val->salt = 0;
9547c478bd9Sstevel@tonic-gate     }
9557c478bd9Sstevel@tonic-gate     val->s2kparams.data = NULL;
9567c478bd9Sstevel@tonic-gate     val->s2kparams.length = 0;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate     end_structure();
9597c478bd9Sstevel@tonic-gate     val->magic = KV5M_ETYPE_INFO_ENTRY;
9607c478bd9Sstevel@tonic-gate   }
9617c478bd9Sstevel@tonic-gate   cleanup();
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info(asn1buf *buf, krb5_etype_info_entry ***val )
9657c478bd9Sstevel@tonic-gate {
9667c478bd9Sstevel@tonic-gate   decode_array_body(krb5_etype_info_entry,asn1_decode_etype_info_entry);
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_etype_info2(asn1buf *buf, krb5_etype_info_entry ***val ,
9707c478bd9Sstevel@tonic-gate 					krb5_boolean v1_3_behavior)
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate     if (v1_3_behavior) {
9737c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
9747c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry_1_3);
9757c478bd9Sstevel@tonic-gate     } else {
9767c478bd9Sstevel@tonic-gate 	decode_array_body(krb5_etype_info_entry,
9777c478bd9Sstevel@tonic-gate 			  asn1_decode_etype_info2_entry);
9787c478bd9Sstevel@tonic-gate     }
9797c478bd9Sstevel@tonic-gate }
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_passwdsequence(asn1buf *buf, passwd_phrase_element *val)
9827c478bd9Sstevel@tonic-gate {
9837c478bd9Sstevel@tonic-gate   setup();
9847c478bd9Sstevel@tonic-gate   { begin_structure();
9857c478bd9Sstevel@tonic-gate     alloc_field(val->passwd,krb5_data);
9867c478bd9Sstevel@tonic-gate     get_lenfield(val->passwd->length,val->passwd->data,
9877c478bd9Sstevel@tonic-gate 		 0,asn1_decode_charstring);
9887c478bd9Sstevel@tonic-gate     val->passwd->magic = KV5M_DATA;
9897c478bd9Sstevel@tonic-gate     alloc_field(val->phrase,krb5_data);
9907c478bd9Sstevel@tonic-gate     get_lenfield(val->phrase->length,val->phrase->data,
9917c478bd9Sstevel@tonic-gate 		 1,asn1_decode_charstring);
9927c478bd9Sstevel@tonic-gate     val->phrase->magic = KV5M_DATA;
9937c478bd9Sstevel@tonic-gate     end_structure();
9947c478bd9Sstevel@tonic-gate     val->magic = KV5M_PASSWD_PHRASE_ELEMENT;
9957c478bd9Sstevel@tonic-gate   }
9967c478bd9Sstevel@tonic-gate   cleanup();
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sequence_of_passwdsequence(asn1buf *buf, passwd_phrase_element ***val)
10007c478bd9Sstevel@tonic-gate {
10017c478bd9Sstevel@tonic-gate   decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_flags(asn1buf *buf, krb5_flags *val)
10057c478bd9Sstevel@tonic-gate { return asn1_decode_krb5_flags(buf,val); }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate #define opt_string(val,n,fn) opt_lenfield((val).length,(val).data,n,fn)
10087c478bd9Sstevel@tonic-gate #define opt_cksum(var,tagexpect,decoder)\
10097c478bd9Sstevel@tonic-gate if(tagnum == (tagexpect)){\
10107c478bd9Sstevel@tonic-gate   get_field_body(var,decoder); }\
10117c478bd9Sstevel@tonic-gate else var.length = 0
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge(asn1buf *buf, krb5_sam_challenge *val)
10147c478bd9Sstevel@tonic-gate {
10157c478bd9Sstevel@tonic-gate   setup();
10167c478bd9Sstevel@tonic-gate   { begin_structure();
10177c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
10187c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10197c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
10207c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
10217c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
10227c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
10237c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
10247c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
10257c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,8,asn1_decode_int32,0);
10267c478bd9Sstevel@tonic-gate     opt_cksum(val->sam_cksum,9,asn1_decode_checksum);
10277c478bd9Sstevel@tonic-gate     end_structure();
10287c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
10297c478bd9Sstevel@tonic-gate   }
10307c478bd9Sstevel@tonic-gate   cleanup();
10317c478bd9Sstevel@tonic-gate }
10327c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2(asn1buf *buf, krb5_sam_challenge_2 *val)
10337c478bd9Sstevel@tonic-gate {
10347c478bd9Sstevel@tonic-gate   setup();
10357c478bd9Sstevel@tonic-gate   { char *save, *end;
10367c478bd9Sstevel@tonic-gate     size_t alloclen;
10377c478bd9Sstevel@tonic-gate     begin_structure();
10387c478bd9Sstevel@tonic-gate     if (tagnum != 0) return ASN1_MISSING_FIELD;
10397c478bd9Sstevel@tonic-gate     if (asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
10407c478bd9Sstevel@tonic-gate       return ASN1_BAD_ID;
10417c478bd9Sstevel@tonic-gate     save = subbuf.next;
10427c478bd9Sstevel@tonic-gate     { sequence_of_no_tagvars(&subbuf);
10437c478bd9Sstevel@tonic-gate       unused_var(size);
10447c478bd9Sstevel@tonic-gate       end_sequence_of_no_tagvars(&subbuf);
10457c478bd9Sstevel@tonic-gate     }
10467c478bd9Sstevel@tonic-gate     end = subbuf.next;
10477c478bd9Sstevel@tonic-gate     alloclen = end - save;
10487c478bd9Sstevel@tonic-gate     if ((val->sam_challenge_2_body.data = (char *) malloc(alloclen)) == NULL)
10497c478bd9Sstevel@tonic-gate       return ENOMEM;
10507c478bd9Sstevel@tonic-gate     val->sam_challenge_2_body.length = alloclen;
10517c478bd9Sstevel@tonic-gate     memcpy(val->sam_challenge_2_body.data, save, alloclen);
10527c478bd9Sstevel@tonic-gate     next_tag();
10537c478bd9Sstevel@tonic-gate     get_field(val->sam_cksum, 1, asn1_decode_sequence_of_checksum);
10547c478bd9Sstevel@tonic-gate     end_structure();
10557c478bd9Sstevel@tonic-gate   }
10567c478bd9Sstevel@tonic-gate   cleanup();
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_challenge_2_body(asn1buf *buf, krb5_sam_challenge_2_body *val)
10597c478bd9Sstevel@tonic-gate {
10607c478bd9Sstevel@tonic-gate   setup();
10617c478bd9Sstevel@tonic-gate   { begin_structure();
10627c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
10637c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
10647c478bd9Sstevel@tonic-gate     opt_string(val->sam_type_name,2,asn1_decode_charstring);
10657c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,3,asn1_decode_charstring);
10667c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge_label,4,asn1_decode_charstring);
10677c478bd9Sstevel@tonic-gate     opt_string(val->sam_challenge,5,asn1_decode_charstring);
10687c478bd9Sstevel@tonic-gate     opt_string(val->sam_response_prompt,6,asn1_decode_charstring);
10697c478bd9Sstevel@tonic-gate     opt_string(val->sam_pk_for_sad,7,asn1_decode_charstring);
10707c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,8,asn1_decode_int32);
10717c478bd9Sstevel@tonic-gate     get_field(val->sam_etype, 9, asn1_decode_int32);
10727c478bd9Sstevel@tonic-gate     end_structure();
10737c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_CHALLENGE;
10747c478bd9Sstevel@tonic-gate   }
10757c478bd9Sstevel@tonic-gate   cleanup();
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_key(asn1buf *buf, krb5_sam_key *val)
10787c478bd9Sstevel@tonic-gate {
10797c478bd9Sstevel@tonic-gate   setup();
10807c478bd9Sstevel@tonic-gate   { begin_structure();
10817c478bd9Sstevel@tonic-gate     /* alloc_field(val->sam_key,krb5_keyblock); */
10827c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
10837c478bd9Sstevel@tonic-gate     end_structure();
10847c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_KEY;
10857c478bd9Sstevel@tonic-gate   }
10867c478bd9Sstevel@tonic-gate   cleanup();
10877c478bd9Sstevel@tonic-gate }
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc(asn1buf *buf, krb5_enc_sam_response_enc *val)
10907c478bd9Sstevel@tonic-gate {
10917c478bd9Sstevel@tonic-gate   setup();
10927c478bd9Sstevel@tonic-gate   { begin_structure();
10937c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,0,asn1_decode_int32,0);
10947c478bd9Sstevel@tonic-gate     opt_field(val->sam_timestamp,1,asn1_decode_kerberos_time,0);
10957c478bd9Sstevel@tonic-gate     opt_field(val->sam_usec,2,asn1_decode_int32,0);
10967c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,3,asn1_decode_charstring);
10977c478bd9Sstevel@tonic-gate     end_structure();
10987c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC;
10997c478bd9Sstevel@tonic-gate   }
11007c478bd9Sstevel@tonic-gate   cleanup();
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_enc_sam_response_enc_2(asn1buf *buf, krb5_enc_sam_response_enc_2 *val)
11047c478bd9Sstevel@tonic-gate {
11057c478bd9Sstevel@tonic-gate   setup();
11067c478bd9Sstevel@tonic-gate   { begin_structure();
11077c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,0,asn1_decode_int32);
11087c478bd9Sstevel@tonic-gate     opt_string(val->sam_sad,1,asn1_decode_charstring);
11097c478bd9Sstevel@tonic-gate     end_structure();
11107c478bd9Sstevel@tonic-gate     val->magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
11117c478bd9Sstevel@tonic-gate   }
11127c478bd9Sstevel@tonic-gate   cleanup();
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate #define opt_encfield(fld,tag,fn) \
11167c478bd9Sstevel@tonic-gate     if(tagnum == tag){ \
11177c478bd9Sstevel@tonic-gate       get_field(fld,tag,fn); } \
11187c478bd9Sstevel@tonic-gate     else{\
11197c478bd9Sstevel@tonic-gate       fld.magic = 0;\
11207c478bd9Sstevel@tonic-gate       fld.enctype = 0;\
11217c478bd9Sstevel@tonic-gate       fld.kvno = 0;\
11227c478bd9Sstevel@tonic-gate       fld.ciphertext.data = NULL;\
11237c478bd9Sstevel@tonic-gate       fld.ciphertext.length = 0;\
11247c478bd9Sstevel@tonic-gate     }
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response(asn1buf *buf, krb5_sam_response *val)
11277c478bd9Sstevel@tonic-gate {
11287c478bd9Sstevel@tonic-gate   setup();
11297c478bd9Sstevel@tonic-gate   { begin_structure();
11307c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
11317c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
11327c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
11337c478bd9Sstevel@tonic-gate     opt_encfield(val->sam_enc_key,3,asn1_decode_encrypted_data);
11347c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_ts,4,asn1_decode_encrypted_data);
11357c478bd9Sstevel@tonic-gate     opt_field(val->sam_nonce,5,asn1_decode_int32,0);
11367c478bd9Sstevel@tonic-gate     opt_field(val->sam_patimestamp,6,asn1_decode_kerberos_time,0);
11377c478bd9Sstevel@tonic-gate     end_structure();
11387c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
11397c478bd9Sstevel@tonic-gate   }
11407c478bd9Sstevel@tonic-gate   cleanup();
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_sam_response_2(asn1buf *buf, krb5_sam_response_2 *val)
11447c478bd9Sstevel@tonic-gate {
11457c478bd9Sstevel@tonic-gate   setup();
11467c478bd9Sstevel@tonic-gate   { begin_structure();
11477c478bd9Sstevel@tonic-gate     get_field(val->sam_type,0,asn1_decode_int32);
11487c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
11497c478bd9Sstevel@tonic-gate     opt_string(val->sam_track_id,2,asn1_decode_charstring);
11507c478bd9Sstevel@tonic-gate     get_field(val->sam_enc_nonce_or_sad,3,asn1_decode_encrypted_data);
11517c478bd9Sstevel@tonic-gate     get_field(val->sam_nonce,4,asn1_decode_int32);
11527c478bd9Sstevel@tonic-gate     end_structure();
11537c478bd9Sstevel@tonic-gate     val->magic = KV5M_SAM_RESPONSE;
11547c478bd9Sstevel@tonic-gate   }
11557c478bd9Sstevel@tonic-gate   cleanup();
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_sam_response *val)
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate   setup();
11627c478bd9Sstevel@tonic-gate   { begin_structure();
11637c478bd9Sstevel@tonic-gate     get_field(val->sam_key,0,asn1_decode_encryption_key);
11647c478bd9Sstevel@tonic-gate     get_field(val->sam_flags,1,asn1_decode_sam_flags);
11657c478bd9Sstevel@tonic-gate     get_field(val->stime,2,asn1_decode_kerberos_time);
11667c478bd9Sstevel@tonic-gate     get_field(val->susec,3,asn1_decode_int32);
11677c478bd9Sstevel@tonic-gate     alloc_field(val->client,krb5_principal_data);
11687c478bd9Sstevel@tonic-gate     get_field(val->client,4,asn1_decode_realm);
11697c478bd9Sstevel@tonic-gate     get_field(val->client,5,asn1_decode_principal_name);
11707c478bd9Sstevel@tonic-gate     opt_string(val->msd,6,asn1_decode_charstring); /* should be octet */
11717c478bd9Sstevel@tonic-gate     end_structure();
11727c478bd9Sstevel@tonic-gate     val->magic = KV5M_PREDICTED_SAM_RESPONSE;
11737c478bd9Sstevel@tonic-gate   }
11747c478bd9Sstevel@tonic-gate   cleanup();
11757c478bd9Sstevel@tonic-gate }
1176*159d09a2SMark Phalan 
1177*159d09a2SMark Phalan /* PKINIT */
1178*159d09a2SMark Phalan 
1179*159d09a2SMark Phalan asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val)
1180*159d09a2SMark Phalan {
1181*159d09a2SMark Phalan     setup();
1182*159d09a2SMark Phalan     {
1183*159d09a2SMark Phalan       begin_structure();
1184*159d09a2SMark Phalan       opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0);
1185*159d09a2SMark Phalan       opt_implicit_octet_string(val->issuerAndSerialNumber.length, val->issuerAndSerialNumber.data, 1);
1186*159d09a2SMark Phalan       opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2);
1187*159d09a2SMark Phalan       end_structure();
1188*159d09a2SMark Phalan     }
1189*159d09a2SMark Phalan     cleanup();
1190*159d09a2SMark Phalan }
1191*159d09a2SMark Phalan 
1192*159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val)
1193*159d09a2SMark Phalan {
1194*159d09a2SMark Phalan     decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier);
1195*159d09a2SMark Phalan }
1196*159d09a2SMark Phalan 
1197*159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val)
1198*159d09a2SMark Phalan {
1199*159d09a2SMark Phalan   setup();
1200*159d09a2SMark Phalan   {
1201*159d09a2SMark Phalan     begin_structure();
1202*159d09a2SMark Phalan     get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
1203*159d09a2SMark Phalan     opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_external_principal_identifier, NULL);
1204*159d09a2SMark Phalan     opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2);
1205*159d09a2SMark Phalan     end_structure();
1206*159d09a2SMark Phalan   }
1207*159d09a2SMark Phalan   cleanup();
1208*159d09a2SMark Phalan }
1209*159d09a2SMark Phalan 
1210*159d09a2SMark Phalan #if 0	/* XXX   This needs to be tested!!! XXX */
1211*159d09a2SMark Phalan asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
1212*159d09a2SMark Phalan {
1213*159d09a2SMark Phalan     setup();
1214*159d09a2SMark Phalan     {
1215*159d09a2SMark Phalan       char *start, *end;
1216*159d09a2SMark Phalan       size_t alloclen;
1217*159d09a2SMark Phalan 
1218*159d09a2SMark Phalan       begin_explicit_choice();
1219*159d09a2SMark Phalan       if (t.tagnum == choice_trusted_cas_principalName) {
1220*159d09a2SMark Phalan 	val->choice = choice_trusted_cas_principalName;
1221*159d09a2SMark Phalan       } else if (t.tagnum == choice_trusted_cas_caName) {
1222*159d09a2SMark Phalan 	val->choice = choice_trusted_cas_caName;
1223*159d09a2SMark Phalan 	start = subbuf.next;
1224*159d09a2SMark Phalan 	{
1225*159d09a2SMark Phalan 	  sequence_of_no_tagvars(&subbuf);
1226*159d09a2SMark Phalan 	  unused_var(size);
1227*159d09a2SMark Phalan 	  end_sequence_of_no_tagvars(&subbuf);
1228*159d09a2SMark Phalan 	}
1229*159d09a2SMark Phalan 	end = subbuf.next;
1230*159d09a2SMark Phalan 	alloclen = end - start;
1231*159d09a2SMark Phalan 	val->u.caName.data = malloc(alloclen);
1232*159d09a2SMark Phalan 	if (val->u.caName.data == NULL)
1233*159d09a2SMark Phalan 	  return ENOMEM;
1234*159d09a2SMark Phalan 	memcpy(val->u.caName.data, start, alloclen);
1235*159d09a2SMark Phalan 	val->u.caName.length = alloclen;
1236*159d09a2SMark Phalan 	next_tag();
1237*159d09a2SMark Phalan       } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) {
1238*159d09a2SMark Phalan 	val->choice = choice_trusted_cas_issuerAndSerial;
1239*159d09a2SMark Phalan 	start = subbuf.next;
1240*159d09a2SMark Phalan 	{
1241*159d09a2SMark Phalan 	  sequence_of_no_tagvars(&subbuf);
1242*159d09a2SMark Phalan 	  unused_var(size);
1243*159d09a2SMark Phalan 	  end_sequence_of_no_tagvars(&subbuf);
1244*159d09a2SMark Phalan 	}
1245*159d09a2SMark Phalan 	end = subbuf.next;
1246*159d09a2SMark Phalan 	alloclen = end - start;
1247*159d09a2SMark Phalan 	val->u.issuerAndSerial.data = malloc(alloclen);
1248*159d09a2SMark Phalan 	if (val->u.issuerAndSerial.data == NULL)
1249*159d09a2SMark Phalan 	  return ENOMEM;
1250*159d09a2SMark Phalan 	memcpy(val->u.issuerAndSerial.data, start, alloclen);
1251*159d09a2SMark Phalan 	val->u.issuerAndSerial.length = alloclen;
1252*159d09a2SMark Phalan 	next_tag();
1253*159d09a2SMark Phalan       } else return ASN1_BAD_ID;
1254*159d09a2SMark Phalan       end_explicit_choice();
1255*159d09a2SMark Phalan     }
1256*159d09a2SMark Phalan     cleanup();
1257*159d09a2SMark Phalan }
1258*159d09a2SMark Phalan #else
1259*159d09a2SMark Phalan asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
1260*159d09a2SMark Phalan {
1261*159d09a2SMark Phalan     setup();
1262*159d09a2SMark Phalan     { begin_choice();
1263*159d09a2SMark Phalan       if (tagnum == choice_trusted_cas_principalName) {
1264*159d09a2SMark Phalan 	val->choice = choice_trusted_cas_principalName;
1265*159d09a2SMark Phalan 	asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName));
1266*159d09a2SMark Phalan       } else if (tagnum == choice_trusted_cas_caName) {
1267*159d09a2SMark Phalan 	val->choice = choice_trusted_cas_caName;
1268*159d09a2SMark Phalan 	get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName);
1269*159d09a2SMark Phalan       } else if (tagnum == choice_trusted_cas_issuerAndSerial) {
1270*159d09a2SMark Phalan 	val->choice = choice_trusted_cas_issuerAndSerial;
1271*159d09a2SMark Phalan 	get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data,
1272*159d09a2SMark Phalan 				  choice_trusted_cas_issuerAndSerial);
1273*159d09a2SMark Phalan       } else return ASN1_BAD_ID;
1274*159d09a2SMark Phalan       end_choice();
1275*159d09a2SMark Phalan     }
1276*159d09a2SMark Phalan     cleanup();
1277*159d09a2SMark Phalan }
1278*159d09a2SMark Phalan #endif
1279*159d09a2SMark Phalan 
1280*159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val)
1281*159d09a2SMark Phalan {
1282*159d09a2SMark Phalan     decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca);
1283*159d09a2SMark Phalan }
1284*159d09a2SMark Phalan 
1285*159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val)
1286*159d09a2SMark Phalan {
1287*159d09a2SMark Phalan   setup();
1288*159d09a2SMark Phalan   { begin_structure();
1289*159d09a2SMark Phalan     get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
1290*159d09a2SMark Phalan     opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL);
1291*159d09a2SMark Phalan     opt_lenfield(val->kdcCert.length, val->kdcCert.data, 2, asn1_decode_octetstring);
1292*159d09a2SMark Phalan     opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring);
1293*159d09a2SMark Phalan     end_structure();
1294*159d09a2SMark Phalan   }
1295*159d09a2SMark Phalan   cleanup();
1296*159d09a2SMark Phalan }
1297*159d09a2SMark Phalan 
1298*159d09a2SMark Phalan asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val)
1299*159d09a2SMark Phalan {
1300*159d09a2SMark Phalan     setup();
1301*159d09a2SMark Phalan     { begin_structure();
1302*159d09a2SMark Phalan       get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0);
1303*159d09a2SMark Phalan 
1304*159d09a2SMark Phalan       opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring);
1305*159d09a2SMark Phalan       end_structure();
1306*159d09a2SMark Phalan     }
1307*159d09a2SMark Phalan     cleanup();
1308*159d09a2SMark Phalan }
1309*159d09a2SMark Phalan 
1310*159d09a2SMark Phalan asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val)
1311*159d09a2SMark Phalan {
1312*159d09a2SMark Phalan     setup();
1313*159d09a2SMark Phalan     { begin_structure();
1314*159d09a2SMark Phalan       get_field(val->cusec, 0, asn1_decode_int32);
1315*159d09a2SMark Phalan       get_field(val->ctime, 1, asn1_decode_kerberos_time);
1316*159d09a2SMark Phalan       get_field(val->nonce, 2, asn1_decode_int32);
1317*159d09a2SMark Phalan       opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring);
1318*159d09a2SMark Phalan       end_structure();
1319*159d09a2SMark Phalan     }
1320*159d09a2SMark Phalan     cleanup();
1321*159d09a2SMark Phalan }
1322*159d09a2SMark Phalan 
1323*159d09a2SMark Phalan asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val)
1324*159d09a2SMark Phalan {
1325*159d09a2SMark Phalan     setup();
1326*159d09a2SMark Phalan     { begin_structure();
1327*159d09a2SMark Phalan       alloc_field(val->kdcName,krb5_principal_data);
1328*159d09a2SMark Phalan       get_field(val->kdcName, 0, asn1_decode_principal_name);
1329*159d09a2SMark Phalan       get_field(val->kdcName, 1, asn1_decode_realm);
1330*159d09a2SMark Phalan       get_field(val->cusec, 2, asn1_decode_int32);
1331*159d09a2SMark Phalan       get_field(val->ctime, 3, asn1_decode_kerberos_time);
1332*159d09a2SMark Phalan       get_field(val->nonce, 4, asn1_decode_int32);
1333*159d09a2SMark Phalan       end_structure();
1334*159d09a2SMark Phalan     }
1335*159d09a2SMark Phalan     cleanup();
1336*159d09a2SMark Phalan }
1337*159d09a2SMark Phalan 
1338*159d09a2SMark Phalan asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf,  krb5_algorithm_identifier *val) {
1339*159d09a2SMark Phalan 
1340*159d09a2SMark Phalan   setup();
1341*159d09a2SMark Phalan   { begin_structure_no_tag();
1342*159d09a2SMark Phalan     /*
1343*159d09a2SMark Phalan      * Forbid indefinite encoding because we don't read enough tag
1344*159d09a2SMark Phalan      * information from the trailing octets ("ANY DEFINED BY") to
1345*159d09a2SMark Phalan      * synchronize EOC tags, etc.
1346*159d09a2SMark Phalan      */
1347*159d09a2SMark Phalan     if (seqindef) return ASN1_BAD_FORMAT;
1348*159d09a2SMark Phalan     /*
1349*159d09a2SMark Phalan      * Set up tag variables because we don't actually call anything
1350*159d09a2SMark Phalan      * that fetches tag info for us; it's all buried in the decoder
1351*159d09a2SMark Phalan      * primitives.
1352*159d09a2SMark Phalan      */
1353*159d09a2SMark Phalan     tagnum = ASN1_TAGNUM_CEILING;
1354*159d09a2SMark Phalan     asn1class = UNIVERSAL;
1355*159d09a2SMark Phalan     construction = PRIMITIVE;
1356*159d09a2SMark Phalan     taglen = 0;
1357*159d09a2SMark Phalan     indef = 0;
1358*159d09a2SMark Phalan     retval = asn1_decode_oid(&subbuf, &val->algorithm.length,
1359*159d09a2SMark Phalan 			     &val->algorithm.data);
1360*159d09a2SMark Phalan     if(retval) return retval;
1361*159d09a2SMark Phalan     val->parameters.length = 0;
1362*159d09a2SMark Phalan     val->parameters.data = NULL;
1363*159d09a2SMark Phalan 
1364*159d09a2SMark Phalan     if(length > subbuf.next - subbuf.base) {
1365*159d09a2SMark Phalan       unsigned int size = length - (subbuf.next - subbuf.base);
1366*159d09a2SMark Phalan       retval = asn1buf_remove_octetstring(&subbuf, size,
1367*159d09a2SMark Phalan 					  &val->parameters.data);
1368*159d09a2SMark Phalan       if(retval) return retval;
1369*159d09a2SMark Phalan       val->parameters.length = size;
1370*159d09a2SMark Phalan     }
1371*159d09a2SMark Phalan 
1372*159d09a2SMark Phalan     end_structure();
1373*159d09a2SMark Phalan   }
1374*159d09a2SMark Phalan   cleanup();
1375*159d09a2SMark Phalan }
1376*159d09a2SMark Phalan 
1377*159d09a2SMark Phalan asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val)
1378*159d09a2SMark Phalan {
1379*159d09a2SMark Phalan     asn1_octet unused;
1380*159d09a2SMark Phalan     setup();
1381*159d09a2SMark Phalan     { begin_structure_no_tag();
1382*159d09a2SMark Phalan 
1383*159d09a2SMark Phalan       retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm);
1384*159d09a2SMark Phalan       if (retval) return retval;
1385*159d09a2SMark Phalan 
1386*159d09a2SMark Phalan       /* SubjectPublicKey encoded as a BIT STRING */
1387*159d09a2SMark Phalan       next_tag();
1388*159d09a2SMark Phalan       if (asn1class != UNIVERSAL || construction != PRIMITIVE ||
1389*159d09a2SMark Phalan           tagnum != ASN1_BITSTRING)
1390*159d09a2SMark Phalan         return ASN1_BAD_ID;
1391*159d09a2SMark Phalan 
1392*159d09a2SMark Phalan       retval = asn1buf_remove_octet(&subbuf, &unused);
1393*159d09a2SMark Phalan       if(retval) return retval;
1394*159d09a2SMark Phalan 
1395*159d09a2SMark Phalan       /* Number of unused bits must be between 0 and 7. */
1396*159d09a2SMark Phalan       /* What to do if unused is not zero? */
1397*159d09a2SMark Phalan       if (unused > 7) return ASN1_BAD_FORMAT;
1398*159d09a2SMark Phalan       taglen--;
1399*159d09a2SMark Phalan 
1400*159d09a2SMark Phalan       val->subjectPublicKey.length = 0;
1401*159d09a2SMark Phalan       val->subjectPublicKey.data = NULL;
1402*159d09a2SMark Phalan       retval = asn1buf_remove_octetstring(&subbuf, taglen,
1403*159d09a2SMark Phalan 					  &val->subjectPublicKey.data);
1404*159d09a2SMark Phalan       if(retval) return retval;
1405*159d09a2SMark Phalan       val->subjectPublicKey.length = taglen;
1406*159d09a2SMark Phalan       /*
1407*159d09a2SMark Phalan        * We didn't call any macro that does next_tag(); do so now to
1408*159d09a2SMark Phalan        * preload tag of any trailing encodings.
1409*159d09a2SMark Phalan        */
1410*159d09a2SMark Phalan       next_tag();
1411*159d09a2SMark Phalan       end_structure();
1412*159d09a2SMark Phalan     }
1413*159d09a2SMark Phalan     cleanup();
1414*159d09a2SMark Phalan }
1415*159d09a2SMark Phalan 
1416*159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val)
1417*159d09a2SMark Phalan {
1418*159d09a2SMark Phalan     decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier);
1419*159d09a2SMark Phalan }
1420*159d09a2SMark Phalan 
1421*159d09a2SMark Phalan asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val)
1422*159d09a2SMark Phalan {
1423*159d09a2SMark Phalan     setup();
1424*159d09a2SMark Phalan     { begin_structure();
1425*159d09a2SMark Phalan       retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data);
1426*159d09a2SMark Phalan       if(retval) return retval;
1427*159d09a2SMark Phalan       val->subjectPublicKey.length = taglen;
1428*159d09a2SMark Phalan       next_tag();
1429*159d09a2SMark Phalan       get_field(val->nonce, 1, asn1_decode_int32);
1430*159d09a2SMark Phalan       opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0);
1431*159d09a2SMark Phalan       end_structure();
1432*159d09a2SMark Phalan     }
1433*159d09a2SMark Phalan     cleanup();
1434*159d09a2SMark Phalan }
1435*159d09a2SMark Phalan 
1436*159d09a2SMark Phalan asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val)
1437*159d09a2SMark Phalan {
1438*159d09a2SMark Phalan     setup();
1439*159d09a2SMark Phalan     { begin_structure();
1440*159d09a2SMark Phalan       get_field(val->replyKey, 0, asn1_decode_encryption_key);
1441*159d09a2SMark Phalan       get_field(val->asChecksum, 1, asn1_decode_checksum);
1442*159d09a2SMark Phalan       end_structure();
1443*159d09a2SMark Phalan     }
1444*159d09a2SMark Phalan     cleanup();
1445*159d09a2SMark Phalan }
1446*159d09a2SMark Phalan 
1447*159d09a2SMark Phalan asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val)
1448*159d09a2SMark Phalan {
1449*159d09a2SMark Phalan     setup();
1450*159d09a2SMark Phalan     { begin_structure();
1451*159d09a2SMark Phalan       get_field(val->replyKey, 0, asn1_decode_encryption_key);
1452*159d09a2SMark Phalan       get_field(val->nonce, 1, asn1_decode_int32);
1453*159d09a2SMark Phalan       end_structure();
1454*159d09a2SMark Phalan     }
1455*159d09a2SMark Phalan     cleanup();
1456*159d09a2SMark Phalan }
1457*159d09a2SMark Phalan 
1458*159d09a2SMark Phalan 
1459*159d09a2SMark Phalan asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val)
1460*159d09a2SMark Phalan {
1461*159d09a2SMark Phalan     setup();
1462*159d09a2SMark Phalan     { begin_structure();
1463*159d09a2SMark Phalan       get_field(*val, 0, asn1_decode_realm);
1464*159d09a2SMark Phalan       get_field(*val, 1, asn1_decode_principal_name);
1465*159d09a2SMark Phalan       end_structure();
1466*159d09a2SMark Phalan     }
1467*159d09a2SMark Phalan     cleanup();
1468*159d09a2SMark Phalan }
1469*159d09a2SMark Phalan 
1470*159d09a2SMark Phalan asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val)
1471*159d09a2SMark Phalan {
1472*159d09a2SMark Phalan     setup();
1473*159d09a2SMark Phalan     { begin_structure();
1474*159d09a2SMark Phalan       get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator);
1475*159d09a2SMark Phalan       if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); }
1476*159d09a2SMark Phalan       /* can't call opt_field because it does decoder(&subbuf, &(val)); */
1477*159d09a2SMark Phalan       if (asn1buf_remains(&subbuf, seqindef)) {
1478*159d09a2SMark Phalan 	if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
1479*159d09a2SMark Phalan 	    && (tagnum || taglen || asn1class != UNIVERSAL))
1480*159d09a2SMark Phalan 	  return ASN1_BAD_ID;
1481*159d09a2SMark Phalan 	if (tagnum == 1) {
1482*159d09a2SMark Phalan 	  retval = asn1_decode_subject_pk_info(&subbuf,
1483*159d09a2SMark Phalan 					       val->clientPublicValue);
1484*159d09a2SMark Phalan 	  if (!taglen && indef) { get_eoc(); }
1485*159d09a2SMark Phalan 	  next_tag();
1486*159d09a2SMark Phalan 	} else val->clientPublicValue = NULL;
1487*159d09a2SMark Phalan       }
1488*159d09a2SMark Phalan       /* can't call opt_field because it does decoder(&subbuf, &(val)); */
1489*159d09a2SMark Phalan       if (asn1buf_remains(&subbuf, seqindef)) {
1490*159d09a2SMark Phalan         if (tagnum == 2) {
1491*159d09a2SMark Phalan 	  asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes);
1492*159d09a2SMark Phalan 	  if (!taglen && indef) { get_eoc(); }
1493*159d09a2SMark Phalan 	  next_tag();
1494*159d09a2SMark Phalan 	} else val->supportedCMSTypes = NULL;
1495*159d09a2SMark Phalan       }
1496*159d09a2SMark Phalan       opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring);
1497*159d09a2SMark Phalan       end_structure();
1498*159d09a2SMark Phalan     }
1499*159d09a2SMark Phalan     cleanup();
1500*159d09a2SMark Phalan }
1501*159d09a2SMark Phalan 
1502*159d09a2SMark Phalan asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val)
1503*159d09a2SMark Phalan {
1504*159d09a2SMark Phalan     setup();
1505*159d09a2SMark Phalan     { begin_structure();
1506*159d09a2SMark Phalan       get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9);
1507*159d09a2SMark Phalan       if (tagnum == 1) {
1508*159d09a2SMark Phalan 	alloc_field(val->clientPublicValue, krb5_subject_pk_info);
1509*159d09a2SMark Phalan 	/* can't call opt_field because it does decoder(&subbuf, &(val)); */
1510*159d09a2SMark Phalan 	if (asn1buf_remains(&subbuf, seqindef)) {
1511*159d09a2SMark Phalan 	  if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
1512*159d09a2SMark Phalan 	    && (tagnum || taglen || asn1class != UNIVERSAL))
1513*159d09a2SMark Phalan 	    return ASN1_BAD_ID;
1514*159d09a2SMark Phalan 	  if (tagnum == 1) {
1515*159d09a2SMark Phalan 	    retval = asn1_decode_subject_pk_info(&subbuf,
1516*159d09a2SMark Phalan 					         val->clientPublicValue);
1517*159d09a2SMark Phalan 	    if (!taglen && indef) { get_eoc(); }
1518*159d09a2SMark Phalan 	    next_tag();
1519*159d09a2SMark Phalan 	  } else val->clientPublicValue = NULL;
1520*159d09a2SMark Phalan 	}
1521*159d09a2SMark Phalan       }
1522*159d09a2SMark Phalan       end_structure();
1523*159d09a2SMark Phalan     }
1524*159d09a2SMark Phalan     cleanup();
1525*159d09a2SMark Phalan }
1526*159d09a2SMark Phalan 
1527*159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val)
1528*159d09a2SMark Phalan {
1529*159d09a2SMark Phalan   setup();
1530*159d09a2SMark Phalan   { begin_choice();
1531*159d09a2SMark Phalan     if (tagnum == choice_pa_pk_as_rep_dhInfo) {
1532*159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_dhInfo;
1533*159d09a2SMark Phalan       get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info);
1534*159d09a2SMark Phalan     } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) {
1535*159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_encKeyPack;
1536*159d09a2SMark Phalan       get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data,
1537*159d09a2SMark Phalan 				choice_pa_pk_as_rep_encKeyPack);
1538*159d09a2SMark Phalan     } else {
1539*159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_UNKNOWN;
1540*159d09a2SMark Phalan     }
1541*159d09a2SMark Phalan     end_choice();
1542*159d09a2SMark Phalan   }
1543*159d09a2SMark Phalan   cleanup();
1544*159d09a2SMark Phalan }
1545*159d09a2SMark Phalan 
1546*159d09a2SMark Phalan asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val)
1547*159d09a2SMark Phalan {
1548*159d09a2SMark Phalan   setup();
1549*159d09a2SMark Phalan   { begin_structure();
1550*159d09a2SMark Phalan     if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) {
1551*159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
1552*159d09a2SMark Phalan       get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data,
1553*159d09a2SMark Phalan 		    choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring);
1554*159d09a2SMark Phalan     } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) {
1555*159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
1556*159d09a2SMark Phalan       get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data,
1557*159d09a2SMark Phalan 		    choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring);
1558*159d09a2SMark Phalan     } else {
1559*159d09a2SMark Phalan       val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN;
1560*159d09a2SMark Phalan     }
1561*159d09a2SMark Phalan     end_structure();
1562*159d09a2SMark Phalan   }
1563*159d09a2SMark Phalan   cleanup();
1564*159d09a2SMark Phalan }
1565*159d09a2SMark Phalan 
1566*159d09a2SMark Phalan asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val)
1567*159d09a2SMark Phalan {
1568*159d09a2SMark Phalan     decode_array_body(krb5_typed_data,asn1_decode_typed_data);
1569*159d09a2SMark Phalan }
1570*159d09a2SMark Phalan 
1571*159d09a2SMark Phalan asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val)
1572*159d09a2SMark Phalan {
1573*159d09a2SMark Phalan   setup();
1574*159d09a2SMark Phalan   { begin_structure();
1575*159d09a2SMark Phalan     get_field(val->type,0,asn1_decode_int32);
1576*159d09a2SMark Phalan     get_lenfield(val->length,val->data,1,asn1_decode_octetstring);
1577*159d09a2SMark Phalan     end_structure();
1578*159d09a2SMark Phalan   }
1579*159d09a2SMark Phalan   cleanup();
1580*159d09a2SMark Phalan }
1581